From a9b76ef204d2b6c992f07be77f2df18c482d9856 Mon Sep 17 00:00:00 2001 From: Richard Unger Date: Wed, 4 May 2022 18:15:48 +0200 Subject: [PATCH 1/4] fixing typos pointed out by the community --- docs/simplefoc_library/code/current_sense/inline.md | 6 +++--- docs/simplefoc_library/code/current_sense/low_side.md | 8 ++++---- .../closed_loop_control/torque_control/foc_current.md | 2 +- .../closed_loop_control/torque_control/index.md | 4 ++-- .../code/motion_control/open_loop/angle_openloop.md | 6 +++--- .../digging_deeper/theory/FOC_routine.md | 4 ++-- .../digging_deeper/theory/low_pass_filtering.md | 2 +- .../digging_deeper/theory/voltage_torque_control.md | 4 ++-- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/simplefoc_library/code/current_sense/inline.md b/docs/simplefoc_library/code/current_sense/inline.md index 8437de8..d5c28fe 100644 --- a/docs/simplefoc_library/code/current_sense/inline.md +++ b/docs/simplefoc_library/code/current_sense/inline.md @@ -10,14 +10,14 @@ grand_grand_parent: Arduino SimpleFOC ## Current sensing support per MCU architecture -In-line current sensing is currently supported for almost all MCU architectures supported by the SimpleFOClibrary. Only not supported architecture is teh ESP8266 which does not have 2 ADC pins, making it unable to run FOC. +In-line current sensing is currently supported for almost all MCU architectures supported by the SimpleFOClibrary. Only not supported architecture is the ESP8266 which does not have 2 ADC pins, making it unable to run FOC. MCU | In-line Current sensing --- | --- @@ -44,7 +44,7 @@ Portenta H7 | ✔️ // - phC - C phase adc pin (optional) InlineCurrentSense current_sense = InlineCurrentSense(0.01, 20, A0, A1, A2); ``` -To instantiate the inline current sensor using the SimpleFOClibrary just create an instance of the class `InlineCurrentSense`. This class takes as a parameter shunt resistance value `shunt_resistor`, amplification gain `gain` and two or three ADC channel pins depending on the available measuring hardware that you might have. It is important to specify right adc channels for right driver/motor phase. So if your pin `A0` measures the phase current `A` and pin `A1` measures the phase current `B` make sure to put provide them to the constructor in that order. +To instantiate the inline current sensor using the SimpleFOClibrary just create an instance of the class `InlineCurrentSense`. This class takes as a parameter shunt resistance value `shunt_resistor`, amplification gain `gain` and two or three ADC channel pins depending on the available measuring hardware that you might have. It is important to specify right adc channels for right driver/motor phase. So if your pin `A0` measures the phase current `A` and pin `A1` measures the phase current `B` make sure to provide them to the constructor in that order. ### Measuring 2 out of 3 currents Field Oriented Control algorithm can run with both 2 or 3 phase current measurements. If measuring 2 out of 3 currents, when defining your `InlineCurrentSense` class put the flag `_NC` (not connected) to the phase value you are not using. diff --git a/docs/simplefoc_library/code/current_sense/low_side.md b/docs/simplefoc_library/code/current_sense/low_side.md index 5724d74..eba7c5c 100644 --- a/docs/simplefoc_library/code/current_sense/low_side.md +++ b/docs/simplefoc_library/code/current_sense/low_side.md @@ -67,7 +67,7 @@ driver.pwm_frequency = 20000; ####  2. PWM pin considerations -As ADC conversion has to be synchronised with the PWM generated on ALL the phases, it is important that all the PWM generated for all the phases have aligned PWM. Since the microcontrollers usually have more than one timer for PWM generation on its pins, different architectures of microcontrollers have different degrees of alinement in between the PWM generated from different timers. +As ADC conversion has to be synchronised with the PWM generated on ALL the phases, it is important that all the PWM generated for all the phases have aligned PWM. Since the microcontrollers usually have more than one timer for PWM generation on its pins, different architectures of microcontrollers have different degrees of alignment in between the PWM generated from different timers.
@@ -171,10 +171,10 @@ else{ } ``` -Once when your current sense has been intialised and calibrated you can start measuring the currents! +When your current sense has been intialised and calibrated you can start measuring the currents! ## Using the current sense with FOC algorithm -To use the `LowsideCurrentSense` with the FOC algorithm all you need to do is to add it to link it with the `BLDCMotor` you wish to use it with: +To use the `LowsideCurrentSense` with the FOC algorithm all you need to do is link it with the `BLDCMotor` you wish to use it with: ```cpp // link motor and current sense motor.linkCurrentSense(¤t_sense); @@ -272,7 +272,7 @@ See the full example for the Aliexpress DRB8302 based board in the library examp ## Standalone current sense Since the low-side current sense has to be synchornised with PWM of a driver of interest it does not make sense to use it as a stand-alone sensor. -But once when you linked the current sense with the `BLDCMotor` you can use it to read your phase currents, overall current magnitude and DQ currents. +But once you have linked the current sense with the `BLDCMotor` you can use it to read your phase currents, overall current magnitude and DQ currents. Reading the phase currents can be done by calling: ```cpp diff --git a/docs/simplefoc_library/code/motion_control/closed_loop_control/torque_control/foc_current.md b/docs/simplefoc_library/code/motion_control/closed_loop_control/torque_control/foc_current.md index 076afa1..542cfcf 100644 --- a/docs/simplefoc_library/code/motion_control/closed_loop_control/torque_control/foc_current.md +++ b/docs/simplefoc_library/code/motion_control/closed_loop_control/torque_control/foc_current.md @@ -27,7 +27,7 @@ The FOC current torque control algorithm reads the phase currents of the BLDC mo The torque generated in the motor is proportional to the q-axis current iq, making this torque control mode the *true torque control* of a BLDC motor. ## Configuration parameters -In order to make this loop run smoothly the user needs to configure the PID controller parameters of teh `PID_current_q` and Low pass filter `LPF_current_q` time constant. +In order to make this loop run smoothly the user needs to configure the PID controller parameters of the `PID_current_q` and Low pass filter `LPF_current_q` time constant. ```cpp // Q axis // PID parameters - default diff --git a/docs/simplefoc_library/code/motion_control/closed_loop_control/torque_control/index.md b/docs/simplefoc_library/code/motion_control/closed_loop_control/torque_control/index.md index 21e2b2d..eb60e4e 100644 --- a/docs/simplefoc_library/code/motion_control/closed_loop_control/torque_control/index.md +++ b/docs/simplefoc_library/code/motion_control/closed_loop_control/torque_control/index.md @@ -41,7 +41,7 @@ has_toc: False - [DC current mode](dc_current_torque_mode) - `dc_current` - [FOC current mode](foc_current_torque_mode) - `foc_current` -In short **voltage control mode** is the simplest approximation of the motor torque control and it so basic that can be run on any motor+driver+mcu combination out there. **DC current mode** is teh next step of the motor's torque approximation which is much more exact than the voltage mode but requires current sensing and much stronger microcontroller. **FOC current mode** is controls motor's true torque and it is not an approximation, it also requires current sensor and even more processing power than the DC current mode. See in depth explanations in [torque mode docs](torque_control). +In short **voltage control mode** is the simplest approximation of the motor torque control and it so basic that can be run on any motor+driver+mcu combination out there. **DC current mode** is the next step of the motor's torque approximation which is much more exact than the voltage mode but requires current sensing and much stronger microcontroller. **FOC current mode** is controls motor's true torque and it is not an approximation, it also requires current sensor and even more processing power than the DC current mode. See in depth explanations in [torque mode docs](torque_control). This motion control mode is enabled setting the `controller` parameter to: ```cpp @@ -73,7 +73,7 @@ For more information about the source code implementation of the motion control Torque control type | PROS | CONS ----- | ----- | ------ Voltage | ✔️ Very simple and fast
✔️ Good performance with any MCU
✔️ Very smooth on low speeds
✔️ No current sense needed | ❌ Not optimal on high speeds
❌ Cannot control true current draw
❌ Torque is approximated (low error on low speeds) -DC current | ✔️ Can control true current draw
✔️ Suitable for low performance MUCs
✔️ Current limiting | ❌ More complex to execute (slower)
❌ Can achieve lower speeds than voltage mode
❌ Torque is approximated (low error on low speeds)
❌ Needs current sensing +DC current | ✔️ Can control true current draw
✔️ Suitable for low performance MCUs
✔️ Current limiting | ❌ More complex to execute (slower)
❌ Can achieve lower speeds than voltage mode
❌ Torque is approximated (low error on low speeds)
❌ Needs current sensing FOC current | ✔️ True torque control (any velocity)
✔️ Can control true current draw
✔️ Very efficient on higher velocities
✔️ Current limiting | ❌ The most complex to execute (slowest)
❌ Not suitable for low-performing MCUs (can become unstable)
❌ Needs current sensing ### Voltage mode - `voltage` diff --git a/docs/simplefoc_library/code/motion_control/open_loop/angle_openloop.md b/docs/simplefoc_library/code/motion_control/open_loop/angle_openloop.md index d3b9ad4..4908eb2 100644 --- a/docs/simplefoc_library/code/motion_control/open_loop/angle_openloop.md +++ b/docs/simplefoc_library/code/motion_control/open_loop/angle_openloop.md @@ -71,12 +71,12 @@ The angle open-loop control will (if not provided phase resistance) set the volt ```cpp voltage = voltage_limit; // Volts ``` -This is very ineficeint, as for different motors with different phase resistances the same voltage values can produce wildly different currents. -For gimbal motor, you can run it in the open loop with the voltage limits of 5-10 Volts and it will reach the currents of 0.5-2 amps as it has the pahse resistance from 5-15 Ohms. For drone motors, the voltage limits should stay very low, under 1 volt. Because they have pahse resisatnce of 0.05 to 0.2 Ohms. +This is very inefficient, as for different motors with different phase resistances the same voltage values can produce wildly different currents. +For gimbal motor, you can run it in the open loop with the voltage limits of 5-10 Volts and it will reach the currents of 0.5-2 amps as it has the phase resistance from 5-15 Ohms. For drone motors, the voltage limits should stay very low, under 1 volt. Because they have phase resisatnce of 0.05 to 0.2 Ohms. ### Current limiting approaches -We suggest you to provide the motor class with the `phase_resistance` value and set the `motor.current_limit` instead the voltage limit. This current might be surpassed but at least you will know an approximate current your motor is drawing. You can calculate the current the motor is going to be producing by checking the motor resistance `phase_resistance` and evaluating: +We suggest you to provide the motor class with the `phase_resistance` value and set the `motor.current_limit` instead of the voltage limit. This current might be surpassed but at least you will know an approximate current your motor is drawing. You can calculate the current the motor is going to be producing by checking the motor resistance `phase_resistance` and evaluating: ```cpp voltage = current_limit * phase_resistance; // Amps ``` diff --git a/docs/simplefoc_library/digging_deeper/theory/FOC_routine.md b/docs/simplefoc_library/digging_deeper/theory/FOC_routine.md index 597d702..475f79f 100644 --- a/docs/simplefoc_library/digging_deeper/theory/FOC_routine.md +++ b/docs/simplefoc_library/digging_deeper/theory/FOC_routine.md @@ -15,7 +15,7 @@ Field oriented control algorithm's main task is to take user defined voltage -FOC algorithm calculates the phase voltages which create the magnetic field in the motor's rotor which are exactly 90 degrees "behind" the magnetic field of the permanent magnets of the rotor, creating a pushing effect. Here is a very nice animation of what happens inside of the motor when running simplified version of the the FOC called six-step modulation. +FOC algorithm calculates the phase voltages which create the magnetic field in the motor's stator which are exactly 90 degrees "behind" the magnetic field of the permanent magnets of the rotor, creating a pushing effect. Here is a very nice animation of what happens inside of the motor when running simplified version of the the FOC called six-step modulation.

via Gfycat

@@ -192,7 +192,7 @@ Sinusoidal | Space Vector --- | --- | -There are several key differences in between these two algorithms. But in terms of SimpleFOClibrary all that you need to know is that Space Vector algorithm better uses the maximal voltage range of the power supply. In the tables above, you can see that for Uq = 0.5V the magnitude of sine waves generated by the Sinusoidal modulation is exactly equal to 1, and Space vector modulation is not quiet there yet. The "double sine" wave produced by the space vector has lower magnitude by the factor of `2/sqrt(3) = 1.15` which means that it can deliver 15% more power to the motor using same power supply. +There are several key differences in between these two algorithms. But in terms of SimpleFOClibrary all that you need to know is that Space Vector algorithm better uses the maximal voltage range of the power supply. In the tables above, you can see that for Uq = 0.5V the magnitude of sine waves generated by the Sinusoidal modulation is exactly equal to 1, and Space vector modulation is not quite there yet. The "double sine" wave produced by the space vector has lower magnitude by the factor of `2/sqrt(3) = 1.15` which means that it can deliver 15% more power to the motor using same power supply. This means, for your power-supply with the voltage Vpower_supply, when using `SinePWM` you will be able to set maximal Uq = 0.5 Vpower_supply and if using `SpaceVectorPWM` you will be able to set Uq = 0.58 Vpower_supply diff --git a/docs/simplefoc_library/digging_deeper/theory/low_pass_filtering.md b/docs/simplefoc_library/digging_deeper/theory/low_pass_filtering.md index 22e020c..f714669 100644 --- a/docs/simplefoc_library/digging_deeper/theory/low_pass_filtering.md +++ b/docs/simplefoc_library/digging_deeper/theory/low_pass_filtering.md @@ -33,7 +33,7 @@ This makes it a bit more clear what the time constant `Tf` of the Low pass filte alpha = 0.01/(0.01 + 0.001) = 0.91 ``` -Which means that your actual velocity measurement v will influence the filtered value vf with the coefficient `1-alpha = 0.09` which is going to smooth the velocity values considerably (maybe even too much, depends of the application). +Which means that your actual velocity measurement v will influence the filtered value vf with the coefficient `1-alpha = 0.09` which is going to smooth the velocity values considerably (maybe even too much, depending on the application). ## Implementation details diff --git a/docs/simplefoc_library/digging_deeper/theory/voltage_torque_control.md b/docs/simplefoc_library/digging_deeper/theory/voltage_torque_control.md index b2b3d6d..bea15f6 100644 --- a/docs/simplefoc_library/digging_deeper/theory/voltage_torque_control.md +++ b/docs/simplefoc_library/digging_deeper/theory/voltage_torque_control.md @@ -26,13 +26,13 @@ Therefore as for the DC motor we know that the motor torque `T` is directly prop T = I*K ``` Where `K` is the motor constant defined by its hardware. -And we also know that the curren is proportional to the set voltage `U`: +And we also know that the current is proportional to the set voltage `U`: ```cpp I = (U - EMF)/R ``` -Where `R` is the motor resistance and `EMF` is the generated back EMF voltage. Thi equation doesn't take in consideration any dynamics but in general it works good enough. +Where `R` is the motor resistance and `EMF` is the generated back EMF voltage. This equation doesn't take in consideration any dynamics but in general it works good enough. So what we can conclude from all this is that (if we neglect the EMF): ```cpp From c81e7ba429fe6852ad9024b72f159a78ec801b5d Mon Sep 17 00:00:00 2001 From: Richard Unger Date: Tue, 9 Aug 2022 22:10:48 +0200 Subject: [PATCH 2/4] =?UTF-8?q?spelling=20corrections=20thanks=20Carelsber?= =?UTF-8?q?gh=20Stijn=20=F0=9F=87=A7=F0=9F=87=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../code/communication/commander/index.md | 3 +- .../code/communication/commander/motion.md | 2 +- .../code/communication/commander/scalar.md | 2 +- .../code/communication/step_dir.md | 2 +- .../code/current_sense/index.md | 25 +++++----- .../code/current_sense/inline.md | 16 +++---- .../code/current_sense/low_side.md | 25 +++++----- .../drivers/bldc_driver/bldc_driver_3pwm.md | 6 +-- .../drivers/bldc_driver/bldc_driver_6pwm.md | 48 +++++++++---------- docs/simplefoc_library/code/drivers/index.md | 8 ++-- .../code/drivers/stepper_driver/index.md | 6 +-- .../stepper_driver/stepper_driver_2pwm.md | 34 ++++++------- .../stepper_driver/stepper_driver_4pwm.md | 8 ++-- docs/simplefoc_library/code/monitoring.md | 2 +- .../closed_loop_control/angle.md | 4 +- .../torque_control/voltage.md | 2 +- .../closed_loop_control/velocity.md | 2 +- .../open_loop/angle_openloop.md | 2 +- .../open_loop/velocity_openloop.md | 6 +-- .../code/motors/bldc_motors.md | 8 ++-- .../code/motors/stepper_motors.md | 6 +-- .../simplefoc_library/code/sensors/encoder.md | 21 ++++---- .../simplefoc_library/code/sensors/generic.md | 2 +- .../code/sensors/hall_sensor.md | 6 +-- docs/simplefoc_library/code/sensors/index.md | 6 +-- .../sensors/magnetic/magnetic_sensor_pwm.md | 4 +- .../libray_source/communication.md | 2 +- .../libray_source/foc_source.md | 4 +- .../libray_source/motiron_control.md | 4 +- .../theory/low_pass_filtering.md | 2 +- .../digging_deeper/theory/pid_controller.md | 2 +- .../theory/voltage_torque_control.md | 6 +-- .../examples/foc_pendulum.md | 3 +- .../examples/gimbal_velocity_example.md | 2 +- .../examples/position_control_example.md | 2 +- .../examples/stepper_control_nucleo.md | 2 +- .../hardware/drivers/BLDC_drivers.md | 6 +-- .../hardware/mcus/arduinos.md | 2 +- docs/simplefoc_library/hardware/mcus/esp32.md | 2 +- docs/simplefoc_library/hardware/mcus/index.md | 15 +++--- .../hardware/mcus/nRF52_mcu.md | 2 +- .../hardware/mcus/portenta.md | 2 +- .../hardware/mcus/rpi_pico.md | 2 +- .../hardware/setup_examples/drv8302.md | 4 +- 44 files changed, 163 insertions(+), 157 deletions(-) diff --git a/docs/simplefoc_library/code/communication/commander/index.md b/docs/simplefoc_library/code/communication/commander/index.md index 0ad4ec4..4489343 100644 --- a/docs/simplefoc_library/code/communication/commander/index.md +++ b/docs/simplefoc_library/code/communication/commander/index.md @@ -12,7 +12,7 @@ has_toc: false # Commander interface -Commander is a simple and flexible interface monitoring, supervision, configuration and control using the G-code like communication protocol. The communication is based on `ASCII` character command ids which makes simple and efficient to parse on any mcu. After the command id has been received the function attached to this command is called and provided the remaining string of characters received which follows the command character. +Commander is a simple and flexible interface monitoring, supervision, configuration and control using the G-code like communication protocol. The communication is based on `ASCII` character command ids which makes simple and efficient to parse on any MCU. After the command id has been received the function attached to this command is called and provided the remaining string of characters received which follows the command character. @@ -166,7 +166,6 @@ void loop(){ } ``` Or maybe you wish to tune the velocity PID and you and change the target value of the motor and you wish to remove unnecessary memory overhead due to the other functionalities you do nto necessarily need, then your code could look something like: -something like this: ```cpp BLDCMotor motor = ..... Commander commander = .... diff --git a/docs/simplefoc_library/code/communication/commander/motion.md b/docs/simplefoc_library/code/communication/commander/motion.md index 01d9676..fa3f1f3 100644 --- a/docs/simplefoc_library/code/communication/commander/motion.md +++ b/docs/simplefoc_library/code/communication/commander/motion.md @@ -25,7 +25,7 @@ Motion control interface in the `Commander` can be integrated in user's applicat ## Target setting in one line -Commander interface enables the user to set the target value for the motion control as well as the limits at once. However different motion control strategies have different numbers of limits (angle, velocity, torque) so depending of the motion control mode used the behavior of the command will change: +Commander interface enables the user to set the target value for the motion control as well as the limits at once. However different motion control strategies have different numbers of limits (angle, velocity, torque) so depending of the motion control mode used the behaviour of the command will change: This feature is available to the user if any one of the three interfaces is added to the `Commander`. diff --git a/docs/simplefoc_library/code/communication/commander/scalar.md b/docs/simplefoc_library/code/communication/commander/scalar.md index d364aff..bcedcf9 100644 --- a/docs/simplefoc_library/code/communication/commander/scalar.md +++ b/docs/simplefoc_library/code/communication/commander/scalar.md @@ -34,7 +34,7 @@ void loop(){ } ``` -You will be able to configure (set and get) itfrom serial monitor: +You will be able to configure (set and get) it from serial monitor: ```sh $ ? # list available commands A: my variable diff --git a/docs/simplefoc_library/code/communication/step_dir.md b/docs/simplefoc_library/code/communication/step_dir.md index c1072f3..194d3ac 100644 --- a/docs/simplefoc_library/code/communication/step_dir.md +++ b/docs/simplefoc_library/code/communication/step_dir.md @@ -63,7 +63,7 @@ step_dir.attach(&my_value); ```

⚠️ BEWARE: Suboptimal performance

-The simplest forms of communication such as step/dir are designed to be handled in hardware and software, interrupt based, implementation of these communication interfaces is usually not the optimal solution. It will provide the user a good base for testing purposes, but it is hard guarantee long-term robustness. +The simplest forms of communication such as step/dir are designed to be handled in hardware and software, interrupt based, implementation of these communication interfaces is usually not the optimal solution. It will provide the user a good base for testing purposes, but it is hard to guarantee long-term robustness.
diff --git a/docs/simplefoc_library/code/current_sense/index.md b/docs/simplefoc_library/code/current_sense/index.md index cfb0973..28c6b24 100644 --- a/docs/simplefoc_library/code/current_sense/index.md +++ b/docs/simplefoc_library/code/current_sense/index.md @@ -20,7 +20,7 @@ Arduino SimpleFOClibrary ha -up to this moment ( [check the releases ](https://github.com/simplefoc/Arduino-FOC/releases) ), Arduino SimpleFOClibrary supports in-line current sensing for almost all platforms and low-side current sensing on ESP32 boards, stm32 (f1, f4 and g4 families - one motor), samd21 (one motor) and on the stm32 based B_G431B_ESC1 boards (one motor). +up to this moment ( [check the releases ](https://github.com/simplefoc/Arduino-FOC/releases) ), Arduino SimpleFOClibrary supports in-line current sensing for almost all platforms and low-side current sensing on ESP32 boards, stm32 (f1, f4 and g4 families - one motor), SAMD21 (one motor) and on the STM32 based B-G431B-ESC1 boards (one motor). Each one of the current sensing classes will implement all the necessary functionalities for simple and robust implementation of FOC algorithm: - Hardware config @@ -31,7 +31,7 @@ Each one of the current sensing classes will implement all the necessary functio - Adaptive alignment with driver phases - Reading the phase currents - Calculation of the current vector magnitude - - Calculation of the FOC d and q currents + - Calculation of the FOC D and Q currents Each of the implemented classes can be used as stand-alone classes and they can be used to read current values on BLDC driver outputs out of scope of the Arduino SimpleFOClibrary, see example codes in `utils > current_sense_test`. In order for FOC algorithm to work the current sense classes are linked to a `BLDCMotor` class which uses the driver to read the FOC currents. @@ -47,18 +47,19 @@ MCU | In-line | Low-side | High-side --- | --- |--- |--- Arduino (8-bit) | ✔️ | ❌ | ❌ Arduino DUE | ✔️ | ❌ | ❌ -stm32 (in general) | ✔️ | ❌ | ❌ -stm32f1 family | ✔️ | ✔️ (one motor) | ❌ -stm32f4 family | ✔️ | ✔️ (one motor) | ❌ -stm32g4 family | ✔️ | ✔️ (one motor) | ❌ -stm32 B_G431B_ESC1 | ✔️ | ✔️ | ❌ -esp32 | ✔️ | ✔️ | ❌ -esp8266 | ❌ | ❌ | ❌ -samd21 | ✔️ | ✔️ (one motor) | ❌ -samd51 | ✔️ | ❌ | ❌ -teensy | ✔️ | ❌ | ❌ +STM32 (in general) | ✔️ | ❌ | ❌ +STM32F1 family | ✔️ | ✔️ (one motor) | ❌ +STM32F4 family | ✔️ | ✔️ (one motor) | ❌ +STM32G4 family | ✔️ | ✔️ (one motor) | ❌ +STM32 B-G431B-ESC1 | ✔️ | ✔️ | ❌ +ESP32 | ✔️ | ✔️ | ❌ +ESP8266 | ❌ | ❌ | ❌ +SAMD21 | ✔️ | ✔️ (one motor) | ❌ +SAMD51 | ✔️ | ❌ | ❌ +Teensy | ✔️ | ❌ | ❌ Raspberry Pi Pico | ✔️ | ❌ | ❌ Portenta H7 | ✔️ | ❌ | ❌ ## Digging deeper + For more theoretical explanations and source code implementations of the current sensing and its integration into the FOC and motion check out the [digging deeper section](digging_deeper). \ No newline at end of file diff --git a/docs/simplefoc_library/code/current_sense/inline.md b/docs/simplefoc_library/code/current_sense/inline.md index d5c28fe..987231b 100644 --- a/docs/simplefoc_library/code/current_sense/inline.md +++ b/docs/simplefoc_library/code/current_sense/inline.md @@ -17,19 +17,19 @@ Inline current sensing technique is the simplest one to use and the most precise ## Current sensing support per MCU architecture -In-line current sensing is currently supported for almost all MCU architectures supported by the SimpleFOClibrary. Only not supported architecture is the ESP8266 which does not have 2 ADC pins, making it unable to run FOC. +In-line current sensing is currently supported for almost all MCU architectures supported by the SimpleFOClibrary. The only not supported architecture is the ESP8266 which does not have 2 ADC pins, making it unable to run FOC. MCU | In-line Current sensing --- | --- Arduino (8-bit) | ✔️ Arduino DUE | ✔️ -stm32 | ✔️ -stm32 B_G431B_ESC1 | ✔️ -esp32 | ✔️ -esp8266 | ❌ -samd21 | ✔️ -samd51 | ✔️ -teensy | ✔️ +STM32 | ✔️ +STM32 B_G431B_ESC1 | ✔️ +ESP32 | ✔️ +ESP8266 | ❌ +SAMD21 | ✔️ +SAMD51 | ✔️ +Teensy | ✔️ Raspberry Pi Pico | ✔️ Portenta H7 | ✔️ diff --git a/docs/simplefoc_library/code/current_sense/low_side.md b/docs/simplefoc_library/code/current_sense/low_side.md index eba7c5c..e1313ac 100644 --- a/docs/simplefoc_library/code/current_sense/low_side.md +++ b/docs/simplefoc_library/code/current_sense/low_side.md @@ -21,22 +21,22 @@ Low side current sensing for all the architectures is on our road-map and we are ## Current sensing support per MCU architecture -Low side current sensing is currently supported for several MCU architectures supported by the SimpleFOClibrary. ESP32 architecture has the most generic support, supporting multiple motors per chip. Stm32 families f1, f4 and g4 are initially supported and support low-side sensing for only one motor. A special case of the stm32 board is the BG431_ESC1 development kit which has very specific low-side implementation for its hardware configuration, and it is fully supported by the library. Samd21 architecture is under development, it has an initial support for only one motor, but for now as it has not been extensively tested, we suggest not to rely on our implementation. +Low side current sensing is currently supported for several MCU architectures supported by the SimpleFOClibrary. ESP32 architecture has the most generic support, supporting multiple motors per chip. Stm32 families f1, f4 and g4 are initially supported and support low-side sensing for only one motor. A special case of the STM32 board is the B-G431-ESC1 development kit which has very specific low-side implementation for its hardware configuration, and it is fully supported by the library. Samd21 architecture is under development, it has an initial support for only one motor, but for now as it has not been extensively tested, we suggest not to rely on our implementation. MCU | Low-side Current sensing --- | --- Arduino (8-bit) | ❌ Arduino DUE | ❌ -stm32 (in general) |❌ -stm32f1 family | ✔️ (one motor) -stm32f4 family | ✔️ (one motor) -stm32g4 family | ✔️ (one motor) -stm32 B_G431B_ESC1 | ✔️ -esp32 |✔️ -esp8266 | ❌ -samd21 | ✔️/❌ (one motor, poorly tested) -samd51 | ❌ -teensy | ❌ +STM32 (in general) |❌ +STM32f1 family | ✔️ (one motor) +STM32f4 family | ✔️ (one motor) +STM32g4 family | ✔️ (one motor) +STM32 B_G431B_ESC1 | ✔️ +ESP32 |✔️ +ESP8266 | ❌ +SAMD21 | ✔️/❌ (one motor, poorly tested) +SAMD51 | ❌ +Teensy | ❌ Raspberry Pi Pico | ❌ Portenta H7 | ❌ @@ -233,8 +233,7 @@ If you are sure in your configuration and if you wish to skip the alignment proc current_sense.skip_align = true; ``` -For example [AliExpress DRV8302 board](https://fr.aliexpress.com/wholesale?catId=0&initiative_id=SB_20211003032006&SearchText=bldc+drv8302) , you would have a code similar to this: -For example, Arduino SimpleFOCShield v2, you would have a code similar to this: +For example for the [AliExpress DRV8302 board](https://fr.aliexpress.com/wholesale?catId=0&initiative_id=SB_20211003032006&SearchText=bldc+drv8302), you would have code similar to this: ```cpp // one possible combination of current sensing pins for SimpleFOCShield v2 // shunt - 5milliOhm diff --git a/docs/simplefoc_library/code/drivers/bldc_driver/bldc_driver_3pwm.md b/docs/simplefoc_library/code/drivers/bldc_driver/bldc_driver_3pwm.md index 52236f5..5296731 100644 --- a/docs/simplefoc_library/code/drivers/bldc_driver/bldc_driver_3pwm.md +++ b/docs/simplefoc_library/code/drivers/bldc_driver/bldc_driver_3pwm.md @@ -9,7 +9,7 @@ grand_grand_parent: Writing the Code grand_grand_grand_parent: Arduino SimpleFOClibrary --- -# BLDC driver 3PWM - `BLDCDriver3PWM` +# BLDC driver 3 PWM - `BLDCDriver3PWM` This is the class which provides an abstraction layer of most of the common 3PWM bldc drivers out there. Basically any BLDC driver board that can be run using 3PWM signals can be represented with this class. Examples: @@ -17,7 +17,7 @@ Examples: - Arduino SimpleFOC PowerShield - L6234 breakout board - HMBGC v2.2 -- DRV830x ( can be run in 3pwm or 6pwm mode ) +- DRV830x ( can be run in 3 PWM or 6 PWM mode ) - X-NUCLEO-IHM07M1 - etc. @@ -164,7 +164,7 @@ void loop() { } ``` -An example code of the BLDC driver with three enable pins, one for each phase. This code will put one phase at the time to the high-impedance mode and pun 3 and 6 Volts on the remaining two. +An example code of the BLDC driver with three enable pins, one for each phase. This code will put one phase at the time to the high-impedance mode and put 3 and 6 Volts on the remaining two. ```cpp // BLDC driver standalone example #include diff --git a/docs/simplefoc_library/code/drivers/bldc_driver/bldc_driver_6pwm.md b/docs/simplefoc_library/code/drivers/bldc_driver/bldc_driver_6pwm.md index 692b237..e7af5a4 100644 --- a/docs/simplefoc_library/code/drivers/bldc_driver/bldc_driver_6pwm.md +++ b/docs/simplefoc_library/code/drivers/bldc_driver/bldc_driver_6pwm.md @@ -11,12 +11,12 @@ grand_grand_grand_parent: Arduino SimpleF # BLDC driver 6PWM - `BLDCDriver6PWM` -This is the class which provides an abstraction layer of most of the common 6PWM bldc drivers out there. Basically any BLDC driver board that can be run using 6PWM signals can be represented with this class. +This is the class which provides an abstraction layer of most of the common 6 PWM BLDC drivers out there. Basically any BLDC driver board that can be run using 6 PWM signals can be represented with this class. Examples: -- DRV830x ( can be run in 3pwm or 6pwm mode ) +- DRV830x ( can be run in 3 PWM or 6 PWM mode ) - ST B-G431B - X-NUCLEO-IHM08M1 -- Odrive 3.6 +- ODrive 3.6 - etc. @@ -25,7 +25,7 @@ Examples: 6 PWM control mode gives much more freedom for BLDC motor control than 3PWM control since each of the 6 half-bride mosfets can be controlled separately. ## Step 1. Hardware setup -To create the interface to the BLDC driver you need to specify the 6 `pwm` pin numbers for each motor phase and optionally `enable` pin. +To create the interface to the BLDC driver you need to specify the 6 `PWM` pin numbers for each motor phase and optionally `enable` pin. ```cpp // BLDCDriver6PWM( int phA_h, int phA_l, int phB_h, int phB_l, int phC_h, int phC_l, int en) // - phA_h, phA_l - A phase pwm pin high/low pair @@ -39,8 +39,8 @@ BLDCDriver6PWM motor = BLDCDriver6PWM(5,6, 9,10, 3,11, 8);
### Arduino UNO support -Arduino UNO and all the atmega328 based boards have only 6 pwm pins and in order to use the `BLDCDrievr6PWM` we need to use all of them. Those are `3`,`5`,`6`,`9`,`10` and `11`. -Furthermore in order for the algorithm to work well we need to use the pwm pins that belong to the same timer for each high/low side pair of each phase. 7 +Arduino UNO and all the atmega328 based boards have only 6 PWM pins and in order to use the `BLDCDrievr6PWM` we need to use all of them. Those are `3`,`5`,`6`,`9`,`10` and `11`. +Furthermore in order for the algorithm to work well we need to use the PWM pins that belong to the same timer for each high/low side pair of each phase. So Atmega328 pins belonging to the timers are: `TIM0` |`TIM1` |`TIM2` @@ -49,28 +49,28 @@ So Atmega328 pins belonging to the timers are: Therefore it is important that `phA_h` and `phA_l` belong to one timer, `phB_h` and `phB_l` to second timer and `phC_h` and `phC_l` to the last timer. If we decide that phase `A` belongs to the timer `TIM0` we can set `phA_h` either to pin `5` or pin `6`. -### stm32 support +### STM32 support -Stm32 boards have two possible 6pwm modes: -- Hardware 6pwm mode -- Software 6pwm mode +Stm32 boards have two possible 6 PWM modes: +- Hardware 6 PWM mode +- Software 6 PWM mode -#### Hardware 6pwm mode -In hardware 6pwm mode the user uses only one timer, usually Timer 1 for all the 6PWM channels. Stm32 boards usually have at least one timer which has automatic complementary channels which avoids the need for a complicated channel inverting configuration. SimpleFOClibrary automatically enables this control mode if you provide the pins that support this interface to the constructor of the `BLDCDriver6PWM` class. For example, both stm32 Bluepill and stm32 Nucleo boards have this interface supported by pins: +#### Hardware 6 PWM mode +In hardware 6 PWM mode the user uses only one timer, usually Timer 1 for all the 6 PWM channels. Stm32 boards usually have at least one timer which has automatic complementary channels which avoids the need for a complicated channel inverting configuration. SimpleFOClibrary automatically enables this control mode if you provide the pins that support this interface to the constructor of the `BLDCDriver6PWM` class. For example, both STM32 Bluepill and STM32 Nucleo boards have this interface supported by pins: `T1C1` | `T1C2` | `T1C3` | `T1C1N` | `T1C2N` | `T1C3N` --- | --- | ---| ---| ---| --- `PA8` | `PA9` | `PA10` | `PB13` | `PB14` | `PB15` -Where `T1Cx` are the Timer 1 channels and `T1CxN` are their complementary channels (inverted channels). Each pair of `T1Cx` and `T1CxN` is used for one pair of the high/low pwm pins. The library will configure the necessary timers and registers if you provide these pins to the constrictor of the `BLDCDriver6PWM` class. For example: +Where `T1Cx` are the Timer 1 channels and `T1CxN` are their complementary channels (inverted channels). Each pair of `T1Cx` and `T1CxN` is used for one pair of the high/low PWM pins. The library will configure the necessary timers and registers if you provide these pins to the constrictor of the `BLDCDriver6PWM` class. For example: ```cpp // BLDCDriver6PWM( int phA_h, int phA_l, int phB_h, int phB_l, int phC_h, int phC_l, int en) BLDCDriver6PWM motor = BLDCDriver6PWM(PA8, PB13, PA9, PB14, PA10, PB15); ``` -#### Software 6pwm mode -If it is not possible to use the hardware 6pwm mode with your board SimpleFOClibrary enables you to use any two channels of any of the timers as your high/low side pwm pair. Basically, the library will automatically configure the complementary channels on the provided low side pins. The only requirement for this code to work properly is exatcly the same as for the Arudino UNO, each phase high/low pwm pair needs to belong to the same timer. -For example, if we take stm32 Nucleo F401RE board we can take for example: +#### Software 6 PWM mode +If it is not possible to use the hardware 6 PWM mode with your board SimpleFOClibrary enables you to use any two channels of any of the timers as your high/low side PWM pair. Basically, the library will automatically configure the complementary channels on the provided low side pins. The only requirement for this code to work properly is exatcly the same as for the Arudino UNO, each phase high/low PWM pair needs to belong to the same timer. +For example, if we take STM32 Nucleo F401RE board we can take for example: ```cpp // BLDCDriver6PWM( int phA_h, int phA_l, int phB_h, int phB_l, int phC_h, int phC_l, int en) BLDCDriver6PWM motor = BLDCDriver6PWM(7, 2, 6, 3, 5, 4); @@ -92,8 +92,8 @@ Where --- | --- | ---| ---| ---| --- `PA8` | `PA9` | `PB6` | `PB7` | `PB8` | `PB9` -### esp32 support -Esp32 boards support `MCPWM` interface that is intended for this kind of applications. Each ep32 board has two of the `MCPWM` channels and can support two 6PWM drivers. There is no pin specific requirements for the esp32, each pin can be used in pwm mode. But please make sure not to use the pins that have predefined states on boot because this could result malfunction. You can find this information online easily, here is a [YouTube video](https://www.youtube.com/watch?v=c0tMGlJVmkw) with more details. +### ESP32 support +ESP32 boards support `MCPWM` interface that is intended for this kind of applications. Each ESP32 board has two of the `MCPWM` channels and can support two 6 PWM drivers. There is no pin specific requirements for the ESP32, each pin can be used in PWM mode. But please make sure not to use the pins that have predefined states on boot because this could result malfunction. You can find this information online easily, here is a [YouTube video](https://www.youtube.com/watch?v=c0tMGlJVmkw) with more details. ### Low-side current sensing considerations @@ -103,7 +103,7 @@ As ADC conversion has to be synchronised with the PWM generated on ALL the phase

RULE OF THUMB: PWM timer pins

-In order to maximise your chances for the low-side current sensing to work well we suggest to make sure that the PWM pins chosen for your driver all belong to the same Timer. +In order to maximise your chances for the low-side current sensing to work well we suggest to make sure that the PWM pins chosen for your driver all belong to the same timer. Finding out which pins belong to different timers might require some time to be spent in the MCU datasheet 😄 You can also always ask the community for help - community link! @@ -117,7 +117,7 @@ You can also always ask the community for help - -⚠️ Arduino devices based on ATMega328 chips have fixed pwm frequency of 32kHz. +⚠️ Arduino devices based on ATMega328 chips have fixed PWM frequency of 32kHz.
Here is a list of different microcontrollers and their PWM frequency and resolution used with the Arduino SimpleFOClibrary. @@ -158,13 +158,13 @@ driver.pwm_frequency = 20000; // dead_zone [0,1] - default 0.02 - 2% driver.dead_zone = 0.05; ``` -The dead zone parameter is defined as the amount of teh duty cycle that is reserved in between changing the active mosfet. Each time the high/low side is deacitvated and low/high side is activated half of the `dead_zone` is injected. This parameter is equivalent to the dead time, dead_time can be calculated as: +The dead zone parameter is defined as the amount of the duty cycle that is reserved in between changing the active mosfet. Each time the high/low side is deacitvated and low/high side is activated half of the `dead_zone` is injected. This parameter is equivalent to the dead time, dead_time can be calculated as: ```cpp dead_time = 1/pwm_frequency*dead_zone ``` ## Step 2.2 Voltages -Driver class is the one that handles setting the pwm duty cycles to the driver output pins and it is needs to know the DC power supply voltage it is plugged to. +Driver class is the one that handles setting the PWM duty cycles to the driver output pins and it is needs to know the DC power supply voltage it is plugged to. Additionally driver class enables the user to set the absolute DC voltage limit the driver will be set to the output pins. ```cpp // power supply voltage [V] @@ -188,7 +188,7 @@ driver.init(); ## Step 3. Using `BLDCDriver6PWM` in real-time -BLDC driver class was developed to be used with the SimpleFOClibrary and to provide the abstraction layer for FOC algorithm implemented in the `BLDCMotor` class. But the `BLDCDriver3PWM` class can used as a standalone class as well and once can choose to implement any other type of control algorithm using the bldc driver. +BLDC driver class was developed to be used with the SimpleFOClibrary and to provide the abstraction layer for FOC algorithm implemented in the `BLDCMotor` class. But the `BLDCDriver3PWM` class can used as a standalone class as well and once can choose to implement any other type of control algorithm using the BLDC driver. ## FOC algorithm support In the context of the FOC control all the driver usage is done internally by the motion control algorithm and all that is needed to enable is is just link the driver to the `BLDCMotor` class. @@ -198,7 +198,7 @@ motor.linkDriver(&driver) ``` ## Standalone driver -If you wish to use the bldc driver as a standalone device and implement your-own logic around it this can be easily done. Here is an example code of a very simple standalone application. +If you wish to use the BLDC driver as a standalone device and implement your-own logic around it this can be easily done. Here is an example code of a very simple standalone application. ```cpp // BLDC driver standalone example #include diff --git a/docs/simplefoc_library/code/drivers/index.md b/docs/simplefoc_library/code/drivers/index.md index e0d0a61..df9d53b 100644 --- a/docs/simplefoc_library/code/drivers/index.md +++ b/docs/simplefoc_library/code/drivers/index.md @@ -31,14 +31,16 @@ These classes can be used as stand-alone classes and they can be used to set cer ## Driver support per MCU architecture -MCU | 2 PWM mode | 4PWM mode | 3 PWM mode | 6 PWM mode | pwm frequency config +MCU | 2 PWM mode | 4 PWM mode | 3 PWM mode | 6 PWM mode | pwm frequency config --- | --- |--- |--- |--- |--- Arduino (8-bit) | ✔️ | ✔️ | ✔️ | ✔️ | ❌ (32kHz) Arduino DUE | ✔️ | ✔️ | ✔️ | ❌ | ✔️ stm32 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ -esp32 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ +esp32 | ✔️ | ✔️ | ✔️ | ✔️ / ❌* | ✔️ esp8266 | ✔️ | ✔️ | ✔️ | ❌ | ✔️ samd21/51 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ teensy | ✔️ | ✔️ | ✔️ | ❌ | ✔️ Raspberry Pi Pico | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ -Portenta H7 | ✔️ | ✔️ | ✔️ | ❌ | ✔️ \ No newline at end of file +Portenta H7 | ✔️ | ✔️ | ✔️ | ❌ | ✔️ + +* For ESP32, the support for 6 PWM depends on the model of ESP32. The models that have a MCPWM peripheral support 6 PWM, the ones that do not only support the other PWM modes. \ No newline at end of file diff --git a/docs/simplefoc_library/code/drivers/stepper_driver/index.md b/docs/simplefoc_library/code/drivers/stepper_driver/index.md index 85d60b3..6d58847 100644 --- a/docs/simplefoc_library/code/drivers/stepper_driver/index.md +++ b/docs/simplefoc_library/code/drivers/stepper_driver/index.md @@ -20,13 +20,13 @@ Arduino SimpleFOClibrary im - [4PWM ](stepper_driver_4pwm) - class `StepperDriver4PWM` - [2PWM ](stepper_driver_2pwm) - class `StepperDriver2PWM` -Classes `StepperDriver2PWM` and `StepperDriver4PWM` provide an abstraction layer of all the hardware/platform specific code for all the supported platforms: atmega328, esp32, stm32, sam, samd and teensy. +Classes `StepperDriver2PWM` and `StepperDriver4PWM` provide an abstraction layer of all the hardware/platform specific code for all the supported platforms: ATMega328, ESP32, STM32, SAM, SAMD and Teensy. They implement: - PWM configuration - PWM frequency - PWM center-alignment - - Direction channel handling (2PWM) - - Complementary direction channel (2PWM) + - Direction channel handling (2 PWM) + - Complementary direction channel (2 PWM) - PWM duty cycle setting - Voltage limiting diff --git a/docs/simplefoc_library/code/drivers/stepper_driver/stepper_driver_2pwm.md b/docs/simplefoc_library/code/drivers/stepper_driver/stepper_driver_2pwm.md index e5780d8..089e108 100644 --- a/docs/simplefoc_library/code/drivers/stepper_driver/stepper_driver_2pwm.md +++ b/docs/simplefoc_library/code/drivers/stepper_driver/stepper_driver_2pwm.md @@ -18,30 +18,32 @@ Examples: - [VNH2SP30 based boards](https://www.ebay.com/itm/Dual-VNH2SP30-Stepper-Motor-Driver-Module-30A-Monster-Moto-Shield-Replace-L298N/401089386943?hash=item5d62ca59bf:g:NA8AAOSw44BYEvxS) - etc. -There are two common `2PWM` stepper driver architectures +There are two common `2 PWM` stepper driver architectures - With one direction pin per phase (`dirx`) - With two direction pin per phase (`phxa` & `phxb`) -Stepper driver with only one direction pin per phase has integrated inversion hardware in the driver itself which invert both pwm signal and direction pin. THese kinds of drivers are very common because they are intended for running dc motors with a simple pwm/direction interface. Basically, in order to run a stepper motor you need to combine two of these drivers. +Stepper driver with only one direction pin per phase has integrated inversion hardware in the driver itself which invert both PWM signal and direction pin. THese kinds of drivers are very common because they are intended for running dc motors with a simple PWM/direction interface. Basically, in order to run a stepper motor you need to combine two of these drivers. -Stepper driver with two direction pins per phase had internal inversion hardware only for the pwm input but not for the direction input. And therefore it requires these inversions to be done outside, in software. You can imagine that `StepperDriver2PWM` class emulates the hardware circuits that are available in the one direction pin drivers shown above. +Stepper driver with two direction pins per phase had internal inversion hardware only for the PWM input but not for the direction input. And therefore it requires these inversions to be done outside, in software. You can imagine that `StepperDriver2PWM` class emulates the hardware circuits that are available in the one direction pin drivers shown above. ## Step 1. Hardware setup -To create the interface to the stepper driver you need to specify the 2 `pwm` pin numbers, one for each motor phase. In addition to this you can choose to specify two direction pins per phase or just one. Finally you can add optional `enable` pin for each phase `en1` and `en2`. +To create the interface to the stepper driver you need to specify the 2 `PWM` pin numbers, one for each motor phase. In addition to this you can choose to specify two direction pins per phase or just one. Finally you can add an optional `enable` pin for each phase `en1` and `en2`. -For only two direction pins per phase use the constructor: +For two direction pins per phase use the constructor: ```cpp -// StepperDriver4PWM( int pwm1, int ph1A,int ph1B,int pwm2, int ph2A,int ph2B, int en1 (optional), int en2 (optional)) -// - pwm1 - phase 1 pwm pin -// - ph1A, ph1B - phase 1 direction pins -// - pwm2 - phase 2 pwm pin -// - ph2A, ph2B - phase 2 direction pins -// - en1, en2 - enable pins (optional input) -StepperDriver2PWM driver = StepperDriver2PWM(3, 4, 5, 10 , 9 , 8 , 11, 12); + // pwm1 PWM1 phase pwm pin + // in1 IN1A phase dir pins + // pwm2 PWM2 phase pwm pin + // in2 IN2A phase dir pins + // en1 enable pin phase 1 (optional input) + // en2 enable pin phase 2 (optional input) + // StepperDriver2PWM(int pwm1, int* in1, int pwm2, int* in2, int en1 = NOT_SET, int en2 = NOT_SET); +StepperDriver2PWM driver = StepperDriver2PWM(3, {4,5}, 10, {9,8}, 11, 12); ``` + For only one direction pin per phase use the constructor: ```cpp // StepperDriver2PWM( int pwm1,int dir1,int pwm2,int dir2, int en1 (optional), int en2 (optional)) @@ -61,7 +63,7 @@ StepperDriver2PWM driver = StepperDriver2PWM(3, 4, 5, 6, 11, 12); driver.pwm_frequency = 20000; ```
-⚠️ Arduino devices based on ATMega328 chips have fixed pwm frequency of 32kHz. +⚠️ Arduino devices based on ATMega328 chips have fixed PWM frequency of 32kHz.
Here is a list of different microcontrollers and their PWM frequency and resolution used with the Arduino SimpleFOClibrary. @@ -77,7 +79,7 @@ All of these settings are defined in the `drivers/hardware_specific/x_mcu.cpp/h` ## Step 2.2 Voltages -Driver class is the one that handles setting the pwm duty cycles to the driver output pins and it is needs to know the DC power supply voltage it is plugged to. +Driver class is the one that handles setting the PWM duty cycles to the driver output pins and it is needs to know the DC power supply voltage it is plugged to. Additionally driver class enables the user to set the absolute DC voltage limit the driver will be set to the output pins. ```cpp // power supply voltage [V] @@ -101,7 +103,7 @@ driver.init(); ## Step 3. Using encoder in real-time -BLDC driver class was developed to be used with the SimpleFOClibrary and to provide the abstraction layer for FOC algorithm implemented in the `StepperMotor` class. But the `StepperDriver4PWM` class can used as a standalone class as well and once can choose to implement any other type of control algorithm using the bldc driver. +BLDC driver class was developed to be used with the SimpleFOClibrary and to provide the abstraction layer for FOC algorithm implemented in the `StepperMotor` class. But the `StepperDriver4PWM` class can used as a standalone class as well and once can choose to implement any other type of control algorithm using the BLDC driver. ## FOC algorithm support In the context of the FOC control all the driver usage is done internally by the motion control algorithm and all that is needed to enable is is just link the driver to the `StepperMotor` class. @@ -111,7 +113,7 @@ motor.linkDriver(&driver) ``` ## Standalone driver -If you wish to use the bldc driver as a standalone device and implement your-own logic around it this can be easily done. Here is an example code of a very simple standalone application. +If you wish to use the BLDC driver as a standalone device and implement your-own logic around it this can be easily done. Here is an example code of a very simple standalone application. ```cpp // Stepper driver standalone example #include diff --git a/docs/simplefoc_library/code/drivers/stepper_driver/stepper_driver_4pwm.md b/docs/simplefoc_library/code/drivers/stepper_driver/stepper_driver_4pwm.md index dda27cc..40bc5cd 100644 --- a/docs/simplefoc_library/code/drivers/stepper_driver/stepper_driver_4pwm.md +++ b/docs/simplefoc_library/code/drivers/stepper_driver/stepper_driver_4pwm.md @@ -11,9 +11,9 @@ grand_grand_grand_parent: Arduino SimpleF # Stepper Driver - `StepperDriver4PWM` -This is the class which provides an abstraction layer of most of the common 4PWM stepper drivers out there. Basically any stepper driver board that can be run using 4PWM signals can be represented with this class. +This is the class which provides an abstraction layer of most of the common 4 PWM stepper drivers out there. Basically any stepper driver board that can be run using 4 PWM signals can be represented with this class. Examples: -- L298n +- L298N - MX1508 - Shield R3 DC Motor Driver Module - etc. @@ -79,7 +79,7 @@ driver.init(); ## Step 3. Using encoder in real-time -BLDC driver class was developed to be used with the SimpleFOClibrary and to provide the abstraction layer for FOC algorithm implemented in the `StepperMotor` class. But the `StepperDriver4PWM` class can used as a standalone class as well and once can choose to implement any other type of control algorithm using the bldc driver. +BLDC driver class was developed to be used with the SimpleFOClibrary and to provide the abstraction layer for FOC algorithm implemented in the `StepperMotor` class. But the `StepperDriver4PWM` class can used as a standalone class as well and once can choose to implement any other type of control algorithm using the BLDC driver. ## FOC algorithm support In the context of the FOC control all the driver usage is done internally by the motion control algorithm and all that is needed to enable is is just link the driver to the `StepperMotor` class. @@ -89,7 +89,7 @@ motor.linkDriver(&driver) ``` ## Standalone driver -If you wish to use the bldc driver as a standalone device and implement your-own logic around it this can be easily done. Here is an example code of a very simple standalone application. +If you wish to use the BLDC driver as a standalone device and implement your-own logic around it this can be easily done. Here is an example code of a very simple standalone application. ```cpp // Stepper driver standalone example #include diff --git a/docs/simplefoc_library/code/monitoring.md b/docs/simplefoc_library/code/monitoring.md index 57a7cfd..bbcac42 100644 --- a/docs/simplefoc_library/code/monitoring.md +++ b/docs/simplefoc_library/code/monitoring.md @@ -75,7 +75,7 @@ motor.monitor_downsample = 100; // default 10 ``` This variable tells `motor.monitor()` to output the variables to the serial each `monitor_downsample` number of calls. So in short, it will output the variables to the serial each `monitor_downsample` loop calls. -Here is an example of a full comfiguration code: +Here is an example of a full configuration code: ```cpp ... void setup(){ diff --git a/docs/simplefoc_library/code/motion_control/closed_loop_control/angle.md b/docs/simplefoc_library/code/motion_control/closed_loop_control/angle.md index 606951e..0f3454b 100644 --- a/docs/simplefoc_library/code/motion_control/closed_loop_control/angle.md +++ b/docs/simplefoc_library/code/motion_control/closed_loop_control/angle.md @@ -20,7 +20,7 @@ You can test this algorithm by running the examples in `motion_control/position_ ## How it works -The angle/position control closes the control loop around the velocity control loop. And the velocity control closes the control loop around the torque control, regardless which one it is. If it is the voltage mode without phase resistance set, the velocity motion control will set the the torque command using the voltage Uq:: +The angle/position control closes the control loop around the velocity control loop. And the velocity control closes the control loop around the torque control, regardless which one it is. If it is the voltage mode without phase resistance set, the velocity motion control will set the the torque command using the voltage Uq: And if it is any of the current torque control modes (FOC or DC current) or voltage mode with provided phase resistance, the angle motion control will be setting the target current iq to the torque controller: @@ -89,7 +89,7 @@ For the angle control you will be able to see the influence of the velocity LPF Additionally you can configure the `velocity_limit` value of the controller. This value prevents the controller to set too high velocities vd to the motor. - If you make your `velocity_limit` very low your motor will be moving in between desired positions with exactly this velocity. If you keep it high, you will not notice that this variable even exists. 😃 -Finally, each application is a bit different and the chances are you will have to tune the controller values a bit to reach desired behavior. +Finally, each application is a bit different and the chances are you will have to tune the controller values a bit to reach desired behaviour. For more theory about this approach and the source code documentation check the [digging deeper section](digging_deeper). diff --git a/docs/simplefoc_library/code/motion_control/closed_loop_control/torque_control/voltage.md b/docs/simplefoc_library/code/motion_control/closed_loop_control/torque_control/voltage.md index b85e283..7459a5b 100644 --- a/docs/simplefoc_library/code/motion_control/closed_loop_control/torque_control/voltage.md +++ b/docs/simplefoc_library/code/motion_control/closed_loop_control/torque_control/voltage.md @@ -49,7 +49,7 @@ Block diagrams of the three torque control techniques based on voltage control c The voltage control algorithm reads the angle $$a$$ from the position sensor and the gets target $$U_q$$ voltage value from the user and using the FOC algorithm sets the appropriate $$u_a$$, $$u_b$$ and $$u_c$$ voltages to the motor. FOC algorithm ensures that these voltages generate the magnetic force in the motor rotor exactly with 90 degree offset from its permanent magnetic field, which guarantees maximal torque, this is called commutation. -The assumption of the pure voltage control is that the torque generated (which is proportional to the current $$I = k \tau $$) in the motor is proportional the voltage as $$U_q$$ set buy user. Maximal torque corresponds to the maximal $$U_q$$ which is conditioned by the power supply voltage available, and the minimal torque is of course for $$U_q= 0$$. +The assumption of the pure voltage control is that the torque generated (which is proportional to the current $$I = k \tau $$) in the motor is proportional the voltage as $$U_q$$ set by the user. Maximal torque corresponds to the maximal $$U_q$$ which is conditioned by the power supply voltage available, and the minimal torque is of course for $$U_q= 0$$. $$ U_q \approx I = k\tau diff --git a/docs/simplefoc_library/code/motion_control/closed_loop_control/velocity.md b/docs/simplefoc_library/code/motion_control/closed_loop_control/velocity.md index e8cdfc1..8ece87a 100644 --- a/docs/simplefoc_library/code/motion_control/closed_loop_control/velocity.md +++ b/docs/simplefoc_library/code/motion_control/closed_loop_control/velocity.md @@ -20,7 +20,7 @@ You can test this algorithm by running the examples in the `motion_control/veloc ## How it works -The velocity control closes the control loop around the torque control, regardless which one it is. If it is the voltage mode without phase resistance set, the velocity motion control will set the the torque command using the voltage Uq:: +The velocity control closes the control loop around the torque control, regardless which one it is. If it is the voltage mode without phase resistance set, the velocity motion control will set the the torque command using the voltage Uq: diff --git a/docs/simplefoc_library/code/motion_control/open_loop/angle_openloop.md b/docs/simplefoc_library/code/motion_control/open_loop/angle_openloop.md index 4908eb2..231af92 100644 --- a/docs/simplefoc_library/code/motion_control/open_loop/angle_openloop.md +++ b/docs/simplefoc_library/code/motion_control/open_loop/angle_openloop.md @@ -80,7 +80,7 @@ We suggest you to provide the motor class with the `phase_resistance` value and ```cpp voltage = current_limit * phase_resistance; // Amps ``` -The best way to use this control strategy would be to provide both phase resistance value and KV rating of your motor. The the library would be able to calculate he back-emf voltage and much more precisely estimate the consumed current. And with the current and the back-emf current the library can set much more appropriate voltage to the motor. +The best way to use this control strategy would be to provide both phase resistance value and KV rating of your motor. The the library would be able to calculate he back-EMF voltage and much more precisely estimate the consumed current. And with the current and the back-EMF current the library can set much more appropriate voltage to the motor. ```cpp voltage = current_limit*phase_resistance + desired_velocity/KV; // Amps ``` diff --git a/docs/simplefoc_library/code/motion_control/open_loop/velocity_openloop.md b/docs/simplefoc_library/code/motion_control/open_loop/velocity_openloop.md index 086eef1..96c361d 100644 --- a/docs/simplefoc_library/code/motion_control/open_loop/velocity_openloop.md +++ b/docs/simplefoc_library/code/motion_control/open_loop/velocity_openloop.md @@ -64,7 +64,7 @@ The velocity open-loop control will (if not provided phase resistance) set the v ```cpp voltage = voltage_limit; // Volts ``` -This is very ineficeint, as for different motors with different phase resistances the same voltage values can produce wildly different currents. +This is very inefficient, as for different motors with different phase resistances the same voltage values can produce wildly different currents. For gimbal motor, you can run it in the open loop with the voltage limits of 5-10 Volts and it will reach the currents of 0.5-2 amps as it has the pahse resistance from 5-15 Ohms. For drone motors, the voltage limits should stay very low, under 1 volt. Because they have pahse resisatnce of 0.05 to 0.2 Ohms. ### Current limiting approaches @@ -73,7 +73,7 @@ We suggest you to provide the motor class with the `phase_resistance` value and ```cpp voltage = current_limit * phase_resistance; // Amps ``` -The best way to use this control strategy would be to provide both phase resistance value and KV rating of your motor. The the library would be able to calculate he back-emf voltage and much more precisely estimate the consumed current. And with the current and the back-emf current the library can set much more appropriate voltage to the motor. +The best way to use this control strategy would be to provide both phase resistance value and KV rating of your motor. The the library would be able to calculate he back-EMF voltage and much more precisely estimate the consumed current. And with the current and the back-EMF current the library can set much more appropriate voltage to the motor. ```cpp voltage = current_limit*phase_resistance + desired_velocity/KV; // Amps ``` @@ -84,7 +84,7 @@ Also, you can change the voltage/current limit in real-time if you need this kin ## Velocity open-loop control example -Here is one basic example of the velocity open-loop control with the complete configuration. The program will set the target velocity of `2 RAD/s` and maintain it, and the user cna change the target velocity using serial terminal. +Here is one basic example of the velocity open-loop control with the complete configuration. The program will set the target velocity of `2 RAD/s` and maintain it, and the user can change the target velocity using serial terminal. ```cpp // Open loop motor control example diff --git a/docs/simplefoc_library/code/motors/bldc_motors.md b/docs/simplefoc_library/code/motors/bldc_motors.md index 28c6e83..8baac31 100644 --- a/docs/simplefoc_library/code/motors/bldc_motors.md +++ b/docs/simplefoc_library/code/motors/bldc_motors.md @@ -30,7 +30,7 @@ BLDCMotor motor = BLDCMotor(11, 10.5, 120); ```

Pole pair number

-If you are not sure what your pole_paris number is. The library provides an example code to estimate your pole_paris number in the examples examples/utils/calibration/find_pole_pairs_number.ino. +If you are not sure what your pole_pairs number is. The library provides an example code to estimate your pole_pairs number in the examples examples/utils/calibration/find_pole_pairs_number.ino.
@@ -49,7 +49,7 @@ You can also use the provided libray examples `examples/utils/calibration/find_K
-### Motor phase reistance and KV rating +### Motor phase resistance and KV rating Providing the KV rating in combination with the phase resistance (not very used for current based torque modes `foc_current` and `dc_current`) will enable the user to control the motor's current without measuring it. The user will be able to control (and limit) the estimated current of the motor using the voltage control mode. Read more in the [torque control docs](voltage_torque_mode). Working with currents instead of voltages is better in may ways, since the torque of the BLDC motor is proportional to the current and not voltages and especially since the same voltage value will produce very different currents for different motors (due to the different phase resistance). Once when the phase resistance is provided the user will be able to set current limit for its BLDC motor instead of voltage limit which is much easier to understand. @@ -128,7 +128,7 @@ The voltage used for the motor and sensor alignment set the variable `motor.volt motor.voltage_sensor_align = 3; // default 3V ``` -If your sensor is an encoder and if it has an index pin, you can set the index search velocity value by set the variable `motor.velocity_index_search`: +If your sensor is an encoder and it has an index pin, you can set the index search velocity value by setting the variable `motor.velocity_index_search`: ```cpp // incremental encoder index search velocity [rad/s] motor.velocity_index_search = 3; // default 1 rad/s @@ -309,7 +309,7 @@ The faster you can run this function the better, here is approximative loops exe ~ 1.5 ms -Esp32 +ESP32 ~ 100 us ~ 200 us ~ 300 us diff --git a/docs/simplefoc_library/code/motors/stepper_motors.md b/docs/simplefoc_library/code/motors/stepper_motors.md index 118500b..6daf86a 100644 --- a/docs/simplefoc_library/code/motors/stepper_motors.md +++ b/docs/simplefoc_library/code/motors/stepper_motors.md @@ -29,8 +29,8 @@ To create a stepper motor instance you need to specify the number of `pole pairs StepperMotor motor = StepperMotor(50, 1.5, 20.6); ```

Pole pair number

-Most of the stepper motors are 200 step per rotation motors making them 50 pole pair motors. In practice you can know the pole_paris number by dividing the number of steps per rotation by 4.

-If you are not sure what your pole_paris number is. The library provides you an example code to estimate your pole_paris number in the examples examples/utils/calibration/find_pole_pairs_number.ino. +Most of the stepper motors are 200 step per rotation motors making them 50 pole pair motors. In practice you can know the pole_pairs number by dividing the number of steps per rotation by 4.

+If you are not sure what your pole_pairs number is. The library provides you an example code to estimate your pole_pairs number in the examples examples/utils/calibration/find_pole_pairs_number.ino.
@@ -50,7 +50,7 @@ You can also use the provided libray examples `examples/utils/calibration/find_K
-### Motor phase reistance and KV rating +### Motor phase resistance and KV rating Providing the KV rating in combination with the phase resistance (not very used for current based torque modes `foc_current` and `dc_current`) will enable the user to control the motor's current without measuring it. The user will be able to control (and limit) the estimated current of the motor using the voltage control mode. Read more in the [torque control docs](voltage_torque_mode). Working with currents instead of voltages is better in may ways, since the torque of the BLDC motor is proportional to the current and not voltages and especially since the same voltage value will produce very different currents for different motors (due to the different phase resistance). Once when the phase resistance is provided the user will be able to set current limit for its BLDC motor instead of voltage limit which is much easier to understand. diff --git a/docs/simplefoc_library/code/sensors/encoder.md b/docs/simplefoc_library/code/sensors/encoder.md index e5b10c8..1ea956d 100644 --- a/docs/simplefoc_library/code/sensors/encoder.md +++ b/docs/simplefoc_library/code/sensors/encoder.md @@ -34,23 +34,23 @@ encoder.quadrature = Quadrature::OFF; ```

CPR, PPR?!

PPR (pulses per revolution) - this is the physical number of impulses the encoder has per revolution. CPR (counts per revolution) - this is amount you are going to have in your counter after the full rotation of the encoder. Now depending on whether you use quadrature mode (counting each edge of the impulse) or not (counting just the rising edge) you will have different CPR for the same PPR. For quadrature mode you will have CPR = 4xPPR and if not using quadrature mode you will have CPR=PPR
-Additionally the encoder has one more important parameter and this is the pullup location. MAny encoders require pullups and in cases when you have an encoder that needs one and you don't have one on your hands you can use Arduino pullups. That is set by changing the value of the `encoder.pullup` variable. The default value is set to `Pullup::USE_EXTERN` but if you would like to change it to use the MCU ones do: +Additionally the encoder has one more important parameter and this is the pullup location. Many encoders require pullups and in cases when you have an encoder that needs one and you don't have one on your hands you can use Arduino pullups. That is set by changing the value of the `encoder.pullup` variable. The default value is set to `Pullup::USE_EXTERN` but if you would like to change it to use the MCU ones do: ```cpp // check if you need internal pullups // Pullup::USE_EXTERN - external pullup added - default // Pullup::USE_INTERN - needs internal arduino pullup encoder.pullup = Pullup::USE_INTERN; ``` -

Arduino Pullup 20kΩ

Be careful when using internal pullups, Arduino has relatively high valued pullups around 20kΩ, which means that you might have some problems for higher velocities (for shorted impulse durations). Recommended pull-up values are in between 1kΩ and 5kΩ.
+

Arduino Pullup 20kΩ

Be careful when using internal pullups, Arduino has relatively high valued pullups around 20kΩ, which means that you might have some problems for higher velocities (for shorted impulse durations). Recommended pull-up values are between 1kΩ and 5kΩ.
## Step 3. Encoder interrupt setup There are two ways you can run encoders with Simple FOC library. - Using [hardware external interrupt](#hardware-external-interrupt) - - Arduino UNO(Atmega328) pins `2` and `3` + - Arduino UNO(ATmega328) pins `2` and `3` - STM32 boards any pin - ESP32 any pin - Using [software pin change interrupt](#software-pin-change-interrupt) by using a library such as [PciManager library](https://github.com/prampec/arduino-pcimanager) - - Only for Arduino devices (Atmga328 and Atmage2560) + - Only for Arduino devices (ATmega328 and ATmega2560)

Software interrupts

Using the hardware external interrupts usually results in better and more reliable performance but software interrupts will work very well for lower velocities. Especially on boards that just don't have enough hardware interrupt pins, having this functionality basically enables FOC on these boards.
@@ -70,7 +70,7 @@ And provide those functions to the encoder interrupt init function `encoder.enab // enable encoder hardware interrupts encoder.enableInterrupts(doA, doB) ``` -You can name the buffering functions as you wish. It is just important to provide them to the `encoder.enableInterrupts()` function. This procedure is a tradeoff in between scalability and simplicity. This allows you to have more than one encoder connected to the same MCU. All you need to do is to instantiate new `Encoder` class and create new buffer functions. For example: +You can name the buffering functions as you wish. It is just important to provide them to the `encoder.enableInterrupts()` function. This procedure is a tradeoff between scalability and simplicity. This allows you to have more than one encoder connected to the same MCU. All you need to do is to instantiate new `Encoder` class and create new buffer functions. For example: ```cpp // encoder 1 Encoder enc1 = Encoder(...); @@ -96,7 +96,7 @@ In order to read index pin efficiently Simple FOC library enables you to use the ```cpp Encoder encoder = Encoder(pinA, pinB, cpr, index_pin); ``` -If you are using Arduino board such as Arduino Mega and similar and if you have more tha 2 hardware interrupts you can connect your index pin to the hardware interrupt pin (example Arduino Mega pin `21`). Your code will look like: +If you are using Arduino board such as Arduino Mega and similar and if you have more than 2 hardware interrupts you can connect your index pin to the hardware interrupt pin (example Arduino Mega pin `21`). Your code will look like: ```cpp Encoder encoder = Encoder(2,3,600,21); // A and B interrupt routine @@ -112,7 +112,7 @@ void setup(){ ``` The function `enableInterrupts` will handle all the initialization for you. -If yo are using Arduino UNO to run this algorithm and you do not have enough hardware interrupt pins you will need to use software interrupt library such as [PciManager library](https://github.com/prampec/arduino-pcimanager). Arduino UNO code for using an encoder with index can be: +If you are using Arduino UNO to run this algorithm and you do not have enough hardware interrupt pins you will need to use software interrupt library such as [PciManager library](https://github.com/prampec/arduino-pcimanager). Arduino UNO code for using an encoder with index can be: ```cpp Encoder encoder = Encoder(2,3,600,A0); // A and B interrupt routine @@ -132,7 +132,7 @@ void setup(){ ... } ``` -The same procedure can be done for pins `A` and `B` if your application makes you run out of the hardware interrupt pins. Software interrupts are very powerful and produce comparable results to the hardware interrupts especially if you have no other choice. `index` pin produces an interrupt once per rotation, therefore it is not critical, so software or hardware interrupt doesn't change too much in terms of performance. +The same procedure can be done for pins `A` and `B` if your application makes you run out of the hardware interrupt pins. Software interrupts are very powerful and produce comparable results to the hardware interrupts especially if you have no other choice. The `index` pin produces one pulse per rotation, therefore it is not critical, so using software or hardware interrupts doesn't change too much in terms of performance. To explore better the difference in the encoder functions with both hardware and software interrupt approach please check the examples `encoder_example.ino` and `encoder_software_interrupts_example.ino`. @@ -155,7 +155,7 @@ Encoder encoder = Encoder(10, 11, 8192); void doA(){encoder.handleA();} void doB(){encoder.handleB();} ``` -Then you declare listeners `PciListenerImp `: +Next you declare listeners `PciListenerImp `: ```cpp // encoder interrupt init PciListenerImp listenerA(encoder.pinA, doA); @@ -200,12 +200,11 @@ void setup(){ ``` You can look into the `HMBGC_example.ino` example to see this code in action. #### Index pin configuration -Enabling index pin in the case of the software interrupt is very simple. You just need to provide it to the `Encoder` class initialization as additional parameter. +Enabling the index pin in the case of the software interrupt is very simple. You just need to provide it to the `Encoder` class initialization as additional parameter. ```cpp Encoder encoder = Encoder(pinA, pinB, cpr, index_pin); ``` Afterwards you create the same type of callback buffering function as for `A` and `B` channels and using the `PCIManager` tools initialize and register the listener for the `index` channel as for the `A` and `B`. Here is a quick example: -example: ```cpp // class init Encoder encoder = Encoder(9, 10, 8192,11); diff --git a/docs/simplefoc_library/code/sensors/generic.md b/docs/simplefoc_library/code/sensors/generic.md index 9609341..ae6838e 100644 --- a/docs/simplefoc_library/code/sensors/generic.md +++ b/docs/simplefoc_library/code/sensors/generic.md @@ -16,7 +16,7 @@ grand_grand_parent: Arduino SimpleFOC

Software interrupts

Using the hardware external interrupts usually results in better and more reliable performance but software interrupts will work very well for lower velocities. Especially on boards that just don't have enough hardware interrupt pins, having this functionality basically enables FOC on these boards. @@ -86,7 +86,7 @@ void setup(){ ### Software pin change interrupt -For Arduino Uno and boards using Atmega328 chipd, we will have to use the software interrupt library to use Hall senors with this library, because we will need three interrupt pins and Atmega328 has only 2. +For Arduino UNO and other boards using ATmega328 chips, we will have to use the software interrupt library to use Hall senors with this library, because we will need three interrupt pins and ATmega328 has only 2. I suggest using the [PciManager library](https://github.com/prampec/arduino-pcimanager). The steps of using this library in code are very similar to [hardware interrupt](#arduino-hardware-external-interrupt). diff --git a/docs/simplefoc_library/code/sensors/index.md b/docs/simplefoc_library/code/sensors/index.md index 59cc9ca..4b095de 100644 --- a/docs/simplefoc_library/code/sensors/index.md +++ b/docs/simplefoc_library/code/sensors/index.md @@ -11,7 +11,7 @@ grand_parent: Arduino SimpleFOClib --- # Position Sensors -This library supports *off-the-shelf* these types of position sensors: +This library supports these types of *off-the-shelf* position sensors: - [Encoder](encoder): - Sensor that counts `A`, `B` and `index` channels impulses to estimate the position. - Examples: @@ -58,7 +58,7 @@ All classes of sensors are implemented in generic way in order to support as man ## Supporting additional sensors -If you are interested to see what does it take to enable your code to run with different type of sensor or with the communication interface that has nto been implemented in the Arduino SimpleFOClibrary yet, check out the short example [how to implement new sensor source](sensor_support). For more details about the theoretical parts of the code and the source code documentation visit [digging deeper section](digging_deeper). +If you are interested to see what does it take to enable your code to run with different type of sensor or with the communication interface that has not been implemented in the Arduino SimpleFOClibrary yet, check out the short example [how to implement new sensor source](sensor_support). For more details about the theoretical parts of the code and the source code documentation visit [digging deeper section](digging_deeper).

NEW 📢

We've also created a simplified interface for implementing new sensors in a context of the GenericSensor class. With it you can add your custom sensor to the SimpleFOClibrary by implementing only one function. Check the
new sensor class @@ -66,7 +66,7 @@ We've also created a simplified interface for implementing new sensors in a cont

SimpleFOC Community

-Finally, if you have implemented a new type od sensor to the library or you are searching for help to implement some specific sensor type don't hesitate to post in [community forum](https://community.simplefoc.com) +Finally, if you have implemented a new type of sensor to the library or you are searching for help to implement some specific sensor type don't hesitate to post in [community forum](https://community.simplefoc.com) It is always helpful to hear the stories/problems/suggestions of people implementing the code and you might find a lot of answered questions there already! diff --git a/docs/simplefoc_library/code/sensors/magnetic/magnetic_sensor_pwm.md b/docs/simplefoc_library/code/sensors/magnetic/magnetic_sensor_pwm.md index 63938fe..a2fc66c 100644 --- a/docs/simplefoc_library/code/sensors/magnetic/magnetic_sensor_pwm.md +++ b/docs/simplefoc_library/code/sensors/magnetic/magnetic_sensor_pwm.md @@ -70,7 +70,7 @@ Please check the `magnetic_sensor_analog_pwm.ino` example to see more about it.

BEWARE: Blocking support limitations ⚠️

Blocking support for magnetic sensors is arguably has the worst performance out of all the position sensing techniques supported in this library. Each time the code reads the angle from the sensor it will read one pulse and since the magnetic sensor have PWM frequency of around 1kHz, it means the the shortest execution time for reading an angle is around 1ms. -But in case of Arudino UNO and similar MCUs this might be the only option. +But in case of Arduino UNO and similar MCUs this might be the only option.
### Interrupt based implementation @@ -144,7 +144,7 @@ class MagneticSensorPWM{ } ``` -Here is a quick example for AS5048A magnetic sensor using it's pwm output: +Here is a quick example for AS5048A magnetic sensor using its PWM output: ```cpp #include diff --git a/docs/simplefoc_library/digging_deeper/libray_source/communication.md b/docs/simplefoc_library/digging_deeper/libray_source/communication.md index af0344d..4fba137 100644 --- a/docs/simplefoc_library/digging_deeper/libray_source/communication.md +++ b/docs/simplefoc_library/digging_deeper/libray_source/communication.md @@ -10,7 +10,7 @@ grand_grand_parent: Arduino SimpleFOC

NOTE:

For more info about the FOC algorithm theory visit foc theory corner.
+

NOTE:

For more info about the FOC algorithm theory visit FOC theory corner.
The two modulation types and phase voltage calculation is fully implemented in the `setPhaseVoltage()` function. Here's how it looks. ```cpp @@ -256,7 +256,7 @@ int BLDCMotor::absoluteZeroAlign() { ## Real-time execution `loopFOC()` -Finally the only thing that is left to do is run the real-time FOC routine. The code needs to get motor position (form sensor), calculate the electrical angle (`electricAngle()`) from it and set the desired voltage (`motor.voltage_q`) to the motor phases by using `setPhaseVoltage()` function. +Finally the only thing that is left to do is run the real-time FOC routine. The code needs to get motor position (from sensor), calculate the electrical angle (`electricAngle()`) from it and set the desired voltage (`motor.voltage_q`) to the motor phases by using `setPhaseVoltage()` function. diff --git a/docs/simplefoc_library/digging_deeper/libray_source/motiron_control.md b/docs/simplefoc_library/digging_deeper/libray_source/motiron_control.md index 32c3b5b..1860594 100644 --- a/docs/simplefoc_library/digging_deeper/libray_source/motiron_control.md +++ b/docs/simplefoc_library/digging_deeper/libray_source/motiron_control.md @@ -40,7 +40,7 @@ This variable can be changed in real-time as well! ## Real-time execution `move()` -The real-time motion control is executed inside `move()` function. Move function receives executes one of the control loops based on the `controller` variable. The parameter `new_target` of the `move()` function is the target value so be set to the control loop. the `new_target` value is optional and doesn't need ot be set. If it is not se the motion control will use `motor.target` variable. +The real-time motion control is executed inside `move()` function. Move function receives executes one of the control loops based on the `controller` variable. The parameter `new_target` of the `move()` function is the target value so be set to the control loop. The `new_target` value is optional and doesn't need to be set. If it is not set the motion control will use `motor.target` variable. Here is the implementation: ```cpp @@ -142,7 +142,7 @@ float BLDCMotor::velocityPI(float tracking_error) { return controllerPI(tracking_error, PID_velocity); } ``` -The `BLDMotor` class has implemented generic PI controller function called `controllerPI()`. +The `BLDCMotor` class has implemented generic PI controller function called `controllerPI()`. ```cpp // PI controller function float BLDCMotor::controllerPI(float tracking_error, PI_s& cont){ diff --git a/docs/simplefoc_library/digging_deeper/theory/low_pass_filtering.md b/docs/simplefoc_library/digging_deeper/theory/low_pass_filtering.md index f714669..3e6c38b 100644 --- a/docs/simplefoc_library/digging_deeper/theory/low_pass_filtering.md +++ b/docs/simplefoc_library/digging_deeper/theory/low_pass_filtering.md @@ -26,7 +26,7 @@ where:

-This makes it a bit more clear what the time constant `Tf` of the Low pass filter stands for. If your sample time is around 1millisecond (for arduino UNO this can be taken as an average) then setting the +This makes it a bit more clear what the time constant `Tf` of the Low pass filter stands for. If your sample time is around 1millisecond (for Arduino UNO this can be taken as an average) then setting the `Tf` value to `Tf = 0.01` will result in: ```cpp diff --git a/docs/simplefoc_library/digging_deeper/theory/pid_controller.md b/docs/simplefoc_library/digging_deeper/theory/pid_controller.md index 6b0c2a3..efb6859 100644 --- a/docs/simplefoc_library/digging_deeper/theory/pid_controller.md +++ b/docs/simplefoc_library/digging_deeper/theory/pid_controller.md @@ -15,7 +15,7 @@ Transfer function of the PID controller this library implements is:

-Continuos PID is transformed to the discrete domain and can be described as a sum of three components: +Continuous PID is transformed to the discrete domain and can be described as a sum of three components:

diff --git a/docs/simplefoc_library/digging_deeper/theory/voltage_torque_control.md b/docs/simplefoc_library/digging_deeper/theory/voltage_torque_control.md index bea15f6..680b038 100644 --- a/docs/simplefoc_library/digging_deeper/theory/voltage_torque_control.md +++ b/docs/simplefoc_library/digging_deeper/theory/voltage_torque_control.md @@ -18,8 +18,8 @@ In this library we are using the voltage as a substitute for the torque control, The voltage control algorithm reads the angle a from the position sensor and the gets target Uq voltage value from the user and using the FOC algorithm sets the appropriate ua, ub and uc voltages to the motor. FOC algorithm ensures that these voltages generate the magnetic force in the motor rotor exactly with 90 degree offset from its permanent magnetic field, which guarantees maximal torque, this is called commutation. -This is a hard way of achieving exactly the principle of the DC motor. Because, for DC motors, the 90degree angle in between generated magnetic field in rotor and the permanent magnetic field of the stator is performed in hardware, making it trivial for end-user. -Now when you have the 90degree constraint ensured by software (FOC algorithm) you can use this motor as any other voltage controlled DC motor. +This is a hard way of achieving exactly the principle of the DC motor. Because, for DC motors, the 90 degree angle in between generated magnetic field in rotor and the permanent magnetic field of the stator is performed in hardware, making it trivial for end-user. +Now when you have the 90 degree constraint ensured by software (FOC algorithm) you can use this motor as any other voltage controlled DC motor. Therefore as for the DC motor we know that the motor torque `T` is directly proportional to the current `I`: ```cpp @@ -32,7 +32,7 @@ And we also know that the current is proportional to the set voltage `U`: I = (U - EMF)/R ``` -Where `R` is the motor resistance and `EMF` is the generated back EMF voltage. This equation doesn't take in consideration any dynamics but in general it works good enough. +Where `R` is the motor resistance and `EMF` is the generated back EMF voltage. This equation doesn't take in consideration any dynamics but in general it works well enough. So what we can conclude from all this is that (if we neglect the EMF): ```cpp diff --git a/docs/simplefoc_library/examples/foc_pendulum.md b/docs/simplefoc_library/examples/foc_pendulum.md index 26852c7..60fefed 100644 --- a/docs/simplefoc_library/examples/foc_pendulum.md +++ b/docs/simplefoc_library/examples/foc_pendulum.md @@ -19,7 +19,8 @@ This is a very fun project in many ways, and it is intended: - Students in search for a good testing platform for their advanced algorithms - Everyone with a bit of free time and a motivation to create something cool :D -### YouTube demonstration video :D +### YouTube demonstration video 😃 + But for me, the most exciting part of this project was the ability to use the Field Oriented Control algorithm. diff --git a/docs/simplefoc_library/examples/gimbal_velocity_example.md b/docs/simplefoc_library/examples/gimbal_velocity_example.md index 7a064c0..97a1999 100644 --- a/docs/simplefoc_library/examples/gimbal_velocity_example.md +++ b/docs/simplefoc_library/examples/gimbal_velocity_example.md @@ -241,7 +241,7 @@ void setup() { motor.initFOC(); // add target command T - command.add('T', doTarget, "target velocity"); + command.add('T', onTarget, "target velocity"); // monitoring port Serial.begin(115200); diff --git a/docs/simplefoc_library/examples/position_control_example.md b/docs/simplefoc_library/examples/position_control_example.md index c088c2c..8d366c8 100644 --- a/docs/simplefoc_library/examples/position_control_example.md +++ b/docs/simplefoc_library/examples/position_control_example.md @@ -225,7 +225,7 @@ void setup() { motor.initFOC(); // add target command T - command.add('T', doTarget, "target angle"); + command.add('T', onTarget, "target angle"); // monitoring port Serial.begin(115200); diff --git a/docs/simplefoc_library/examples/stepper_control_nucleo.md b/docs/simplefoc_library/examples/stepper_control_nucleo.md index 20ae653..422e531 100644 --- a/docs/simplefoc_library/examples/stepper_control_nucleo.md +++ b/docs/simplefoc_library/examples/stepper_control_nucleo.md @@ -32,7 +32,7 @@ Here is an example of the connection scheme using the L298N and Nucleo-64: ## Encoder - Channels `A` and `B` are connected to the pins `A0` qnd `A1` -- Index channel is not used in this example but you cqn easily modify this example to support it +- Index channel is not used in this example but you can easily modify this example to support it ## Motor - Motor phases `A1`, `A2`, `B1`and `B2` are connected directly the motor connectors of the L298N chip. diff --git a/docs/simplefoc_library/hardware/drivers/BLDC_drivers.md b/docs/simplefoc_library/hardware/drivers/BLDC_drivers.md index f6bbe26..bd09617 100644 --- a/docs/simplefoc_library/hardware/drivers/BLDC_drivers.md +++ b/docs/simplefoc_library/hardware/drivers/BLDC_drivers.md @@ -48,11 +48,11 @@ Examples | Description | Specifications | Link | Price

L298N limitations

L298N is based on bipolar transistor technology and has relatively long transistor rise times which can produce non-smooth operation. We suggest the L298N based boards only in closed loop mode, as the position sensor can correct possible noise from the driver. -It can also be a good board for beginner users, to get familier with the FOC as a cheep solution, but with certain performance limits. +It can also be a good board for beginner users, to get familiar with the FOC as a cheap solution, but with certain performance limits. ## High performance boards -SimpleFOClibrary will support basically any BLDC motor driver which can be controlled using 3 PWM or 6PWM signals. Up to this moment ([version 1.3.1](https://github.com/simplefoc/Arduino-FOC/releases)) the library doesn't implement the current control loop. The motor torque is controlled via voltage directly ([more info](voltage_torque_control)) +SimpleFOClibrary will support basically any BLDC motor driver which can be controlled using 3 PWM or 6 PWM signals. Up to this moment ([version 1.3.1](https://github.com/simplefoc/Arduino-FOC/releases)) the library doesn't implement the current control loop. The motor torque is controlled via voltage directly ([more info](voltage_torque_control)) Here are the boards that have been tested and are compatible with the library: @@ -72,5 +72,5 @@ Examples | Description | Specifications | Link | Price

IFX007T and BTN8982 chips limitations

IFX007T and BTN8982 are based on relatively old transistor technology and have relatively long transistor rise times which can produce non-smooth operation. We suggest the boards based on these chips to be used only in closed loop mode, as the position sensor can correct possible noise from the driver. -It can also be a good board for beginner users, to get familier with the high-current FOC as a cheep solution, but with certain performance limits. +It can also be a good board for beginner users, to get familiar with the high-current FOC as an inexpensive solution, but with certain performance limits. \ No newline at end of file diff --git a/docs/simplefoc_library/hardware/mcus/arduinos.md b/docs/simplefoc_library/hardware/mcus/arduinos.md index 9be5003..6565135 100644 --- a/docs/simplefoc_library/hardware/mcus/arduinos.md +++ b/docs/simplefoc_library/hardware/mcus/arduinos.md @@ -11,7 +11,7 @@ grand_grand_parent: Arduino SimpleFOCSimpleFOCSimpleFOClibrary Make sure your gimbal controller has communication interface pins you need, available before buying it. ## Arduino MCUs -Arduino devices, such as UNO,MEGA,NANO and similar, are probably the most commonly used microcontrollers there is, and therefore probably with this library as well. The simplicity of using these boards si incomparable. If you are planning to run this library with the Arduino device I would certainly suggest you to think about using Magnetic sensors instead of encoders. Encoders are highly inefficient sensors (at least their implementation for Arduino UNO & MEGA) and due to constant counting the interrupt signals of the encoder produces a large difference of execution time depending on velocities you are driving your motor. +Arduino devices, such as UNO, MEGA, NANO and similar, are probably the most commonly used microcontrollers there is, and therefore probably with this library as well. The simplicity of using these boards si incomparable. If you are planning to run this library with the Arduino device I would certainly suggest you to think about using Magnetic sensors instead of encoders. Encoders are highly inefficient sensors (at least their implementation for Arduino UNO & MEGA) and due to constant counting the interrupt signals of the encoder produces a large difference of execution time depending on velocities you are driving your motor.

Encoder CPR: Rule of thumb for Arduino UNO/MEGA

diff --git a/docs/simplefoc_library/hardware/mcus/nRF52_mcu.md b/docs/simplefoc_library/hardware/mcus/nRF52_mcu.md index d9c1a2d..d25ac50 100644 --- a/docs/simplefoc_library/hardware/mcus/nRF52_mcu.md +++ b/docs/simplefoc_library/hardware/mcus/nRF52_mcu.md @@ -11,7 +11,7 @@ grand_grand_parent: Arduino SimpleFOCSimpleFOCSimpleFOCSimpleFOCSimpleFOClibrary. +DRV8302 is a high performance BLDC driver board capable of delivering 15A current continuously and 27A peak current. It has temperature and over-current protection, it has Back EMF and three phase current sensing and last but not the least it can be run using only 3 PWM signals making it compatible with the SimpleFOClibrary. Here is an example of the connection scheme using the Arduino UNO: @@ -33,7 +33,7 @@ You can find this board on [Aliexpress ](http ## Encoder - Channels `A` and `B` are connected to the external interrupt pins `2` and `3` -- If your encoder has `index` signal you can connect it to any available digital pin, here we connected it to the pin `4` +- If your encoder has an `index` signal you can connect it to any available digital pin, here we connected it to the pin `4` ## Motor - Motor phases `a`, `b` and `c` are connected directly the board terminals `OUTA`, `OUTB` and `OUTC` From 58d1be8508f44fc93a5db93296080c2f395f3b73 Mon Sep 17 00:00:00 2001 From: Richard Unger Date: Fri, 17 Feb 2023 08:46:51 +0100 Subject: [PATCH 3/4] added new build flags --- .gitignore | 4 +++- .jekyll-metadata | Bin 53889 -> 0 bytes .../simplefoc_library/cheatsheet/build_flags.md | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) delete mode 100644 .jekyll-metadata diff --git a/.gitignore b/.gitignore index 78050df..50f84c6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ _site Gemfile.lock node_modules -.jekyll-cache \ No newline at end of file +.jekyll-cache +bin/just-the-docs +assets/images/.DS_Store diff --git a/.jekyll-metadata b/.jekyll-metadata deleted file mode 100644 index ebacc0b4c6cdda77372e0794e68028c0abe1b46d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53889 zcmc&-36vDo)pn2!vI?kx8b=%#NMu%4!DSd=bPy2PA}%Rwx@&rhsqSjKx@Q=0nSdf< zOmK$7}Zpp9tjWK35$0g=O;~K@2J^KIuy{}&PRKKOFr@4*icsw(s z-SyRd_kMSI_uV)2u#H33Rkhc)E|}Y}+OslV!`ZHvHZu(i-B>PZrLtZ_!p?T(IvPAX znRcvBH&*Zeq26{IW;D*I@5&~f>baw>RLqUrsYLC#PuZ!s+w0XeHP39^IIO*PL^5k9 zt?Ieei&nMg<_=#4zl>g2Thsr`Ge&F}F?V#zOu0rXm$Zj$uj0SOt&|O4>E$|-b}Zx8 zR=3O@>2`K{R@NRe`QvkkZ*Wsqd+nqZZqiJ}tjQ~L$)uH;j9*+muezSMeuz_Eazq2WbkX39N^cc%%0%a83*`v zJr*otrUB&Ji+#G0C-0C!QPB!?BYYyxivu1~58NC@Zod!J) ze(|Rc?2EZ9Vs0{>vAn=Hw;aB4Sj+JC+`M5-p{J}Jv0>P}k*K5dMzxG=8GX?qEn|!R zk1>~k%FjCt{*OcF4Y#Z3ji{~e7d|kq@Bueo)4y}`qCM;bf33=YV7c&t@r4hdQQhZA z7}{&8m#XkYgxGz(57Ev899s;qy|zN@T0nvC-Pq41d%=)Aj!Q)xl~RKuAd{~4f#}6? zSy|c`cVpfF2OEyvkufuU4P9m?-fL#8hIq#ALHcf8vT%XHf2mK#tC6${0CByZ`zu$e z?FE%;DU#Hvmcv`dwv1~T-*QCDku68H*SZw}oOH8p9258JqSrX`;b87kzd#!Pd%Ff4*nFk)}n1bWV znyEM}V8L|(Wk}Mmx}5TTz)4#TAa2`D88J7N&A3iO%yB&{ZaA)+F8s|*B^>$PGVpFc zc<8e6x_4`7QNF>(O22`dwo(i~I4rQ;}5~7zpTu(xZ9COzPoMUus zEFryu5-C&iJRx>C@fat>hQQCp^mK1h0^bD+?*3@}1g0NX7o7BVBuF$~wSpgf@Uv9l z699hor|<0>9QbZ>$#Z6B!qzZ5LjCf_1wR~|9bQEVRcD7CPR>f(j)PQ~vSN1DO-X8k z))*TzSZhpB!1uar%ZWE6tSoq+gyCh)OxB7wpvp@y-#e+Mf5+dBOreykp3KKZlf%9J zl@uuR;fdfr*`NCi&&_3G7GO>$b16G!qBoMjqaS_BJ7>h;R3t@#UMpi%2m~v$9*X*i zd-s2aq5Xa#22F>{y1jg~=)BEXRuUVk=2??R`i`RHn5nmXAceX>Atq(?TeP@rsUg;Z z2#ROEVq}`Qx~Bi{$Bemw$xnc-C*I1(Mi8T3ma__B5xA0AE|Y<}h$Q$45L*1@xb7Y7 z4FnIZe*=$F@H$G1XL{yLZ)}zzqpqAgew2{3O1?QxiLnsx=s;}+yMJWJHMbAW?z<>4 zG6nXml!pllD{NUANq89NoV|C^p5lyO5*`WZ=jpVtz$^r_y!3Q=QMYZX>3?Hb;~`9b z(+W9WV|WNd8sdhseqI42fg<6*`}WrdN%&Rt!IzL82^0Vo&`=K8duQVpQ1-B!mVhoV1hWWThHamQs`jqe|Gx4%0DuEXRespf8`hONg(7_1^Ze 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 E|Ce|^?f?J) diff --git a/docs/simplefoc_library/cheatsheet/build_flags.md b/docs/simplefoc_library/cheatsheet/build_flags.md index 8cd421f..d387c9d 100644 --- a/docs/simplefoc_library/cheatsheet/build_flags.md +++ b/docs/simplefoc_library/cheatsheet/build_flags.md @@ -21,6 +21,9 @@ Build flags control the way the compiler generates the code for SimpleFOC \ No newline at end of file