Skip to content

Commit 9e93c22

Browse files
authored
Merge pull request #48 from simplefoc/dev
Dev to master - v2.4
2 parents 6c4e651 + 566eac9 commit 9e93c22

File tree

230 files changed

+14248
-5057
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

230 files changed

+14248
-5057
lines changed

Gemfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ gem "bundler"
44
gem "jekyll-seo-tag"
55
gem "jekyll-toc"
66
gem "jekyll-remote-theme"
7-
gem "rake"
7+
gem "rake"
8+
gem "kramdown-parser-gfm"
9+
gem "jekyll-include-cache"

_config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ plugins:
3535

3636

3737
# Footer content appears at the bottom of every page's main content
38-
footer_content: "Copyright &copy; 2024. Distributed by an <a href=\"https://github.com/simplefoc/simplefoc.github.io/tree/master/LICENSE\">MIT license.</a>"
38+
footer_content: "Copyright &copy; 2026. Distributed by an <a href=\"https://github.com/simplefoc/simplefoc.github.io/tree/master/LICENSE\">MIT license.</a>"
3939

4040
# External navigation links
4141
nav_external_links:

docs/simplefoc_library/code/communication/commander/index.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ This g-code like interface provides callback to configure and tune any:
2323
- [PID controllers](commander_pid)
2424
- [Low pass filters](commander_lpf)
2525
- [Scalar variables](commander_scalar)
26-
- [Motion control](commander_target) <b><i>NEW</i>📢</b>
26+
- [Motion control](commander_target)
2727
- Setting target values and limits at once (ex. angle velocity torque)
2828
- Changing the motion and torque control mode
2929
- Enable/Disable the motor
@@ -36,6 +36,10 @@ This g-code like interface provides callback to configure and tune any:
3636
- enable/disable
3737
- sensor offsets
3838
- phase resistance
39+
- read `loopFOC` and `move` time <b><i>NEW</i>📢</b>
40+
- rerun `initFOC` <b><i>NEW</i>📢</b>
41+
- run `characteriseMotor` <b><i>NEW</i>📢</b>
42+
- run `tuneCurrentControllers` <b><i>NEW</i>📢</b>
3943
- ...
4044

4145
Furthermore commander enables you to easily create your own commands and extend this interface in any way you might need for your particular application.

docs/simplefoc_library/code/communication/commander/motion.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Motion control interface in the `Commander` can be integrated in user's applicat
1919
- Change the [motion control](motion_control) mode
2020
- Change the [torque control](torque_control) mode
2121
- Enable/Disable the motor mode
22+
- read the motion and torque loop time (filtered) - read only <b><i>NEW</i>📢</b>
2223
- [Full configuration interface](commander_motor) - `commander.motor(&motor,cmd)`
2324
- All above + full parameter configuration of the motor...
2425

@@ -111,17 +112,22 @@ Target: 50.000
111112
## Motion control interface
112113
The motion control interface enables user to control every aspect of the motion of the motor through the `Commander`. The commands the user has at his disposition are:
113114

114-
- **C** - Motion control type config
115+
- **C** - [Motion control](motion_control) type config
115116
- **D** - downsample motion loop
117+
- **T** - motion loop time in microseconds (filtered) - read only <b><i>NEW</i>📢</b>
116118
- `0` - torque
117119
- `1` - velocity
118120
- `2` - angle
119121
- `3` - velocity_openloop
120-
- `4` - angle_openloop
121-
- **T** - Torque control type
122+
- `4` - angle_openloop
123+
- `5` - angle_nocascade
124+
- `6` - custom
125+
- **T** - [Torque control](torque_control) type
126+
- **T** - motion loop time in microseconds (filtered) - read only <b><i>NEW</i>📢</b>
122127
- `0` - voltage
123128
- `1` - dc_current
124129
- `2` - foc_current
130+
- `3` - estimated_current
125131
- **E** - Motor status (enable/disable)
126132
- `0` - enable
127133
- `1` - disable

docs/simplefoc_library/code/communication/commander/motor.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,28 @@ When using a standard callback for `BLDCMotor` and `StepperMotor` classes:`comma
4444
- **S** - set monitoring variables
4545
- **G** - get variable value
4646
- **C** - Motion control type config - [see motion control](commander_target)
47-
- **D** - downsample motion loop
47+
- **D** - downsample motion loop
48+
- **T** - motion loop time in microseconds (filtered) - read only <b><i>NEW</i>📢</b>
4849
- `0` - torque
4950
- `1` - velocity
5051
- `2` - angle
5152
- `3` - velocity_openloop
5253
- `4` - angle_openloop
54+
- `5` - angle_nocascade
55+
- `6` - custom
5356
- **T** - Torque control type - [see motion control](commander_target)
57+
- **T** - motion loop time in microseconds (filtered) - read only <b><i>NEW</i>📢</b>
5458
- `0` - voltage
5559
- `1` - dc_current
5660
- `2` - foc_current
61+
- `3` - estimated_current
5762
- **E** - Motor status (enable/disable) - [see motion control](commander_target)
5863
- `0` - enable
5964
- `1` - disable
65+
- **F** - Init and tunning actions <b><i>NEW</i>📢</b>
66+
- **R** - rerun motor `initFOC` function
67+
- **P** - run `characteriseMotor` function with the voltage set in the command (ex. `MFP3.5` to run characterisation with 3.5V test voltage)
68+
- **C** - run `tuneCurrentControllers` function with the voltage set in the command (ex. `MFC100.0` to run current controllers tuning with the bandwidth of 100Hz)
6069
- **else** - Target setting interface - [see motion control target](commander_target) <br>
6170
Depends of the motion control mode:
6271
- torque mode - torque target (ex. `M2.5`)

docs/simplefoc_library/code/communication/index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ has_toc: False
1515
- 📈 Supervision and variable monitoring - [Monitoring](monitoring)
1616
- ⚙️ Tunning and Configuration interface - [Commander interface](commander_interface)
1717

18+
[Set up Monitoring](monitoring){: .btn .btn-docs .mr-2}
19+
[Configure Commander interface](commander_interface){: .btn .btn-docs}
20+
1821
Additionally we will try to provide an implementation of the simplest forms of the communication protocols:
1922
- [Step-direction interface](step_dir_interface)
2023
- PWM interface - *not supported yet*
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
---
2+
layout: default
3+
title: Generic Current Sense
4+
description: "Arduino Simple Field Oriented Control (FOC) library ."
5+
permalink: /generic_current_sense
6+
nav_order: 4
7+
parent: Current Sensing
8+
grand_parent: Writing the Code
9+
grand_grand_parent: Arduino <span class="simple">Simple<span class="foc">FOC</span>library</span>
10+
toc: true
11+
---
12+
13+
14+
15+
# Implementing a custom current sense
16+
17+
`GenericCurrentSense` is a helper class that makes it easy to integrate a custom current-sensing setup into the <span class="simple">Simple<span class="foc">FOC</span>library</span>. You provide callbacks to read phase currents (and optionally initialize your hardware), and the library handles offsets, filtering, and integration with FOC control.
18+
19+
For advanced users, you can also implement your own class by inheriting `CurrentSense`, but `GenericCurrentSense` is usually faster to get working.
20+
21+
[See library source code for more details (Advanced)](current_sense_support){: .btn .btn-docs}
22+
23+
## Step 1. Implement the current-reading callback
24+
25+
Provide a function that returns phase currents in **amps**. If you only measure two phases, set the third one to `0`.
26+
27+
```cpp
28+
PhaseCurrent_s readCurrentSense(){
29+
PhaseCurrent_s c;
30+
// Read your ADCs and convert to amps
31+
c.a = ...; // phase A current [A]
32+
c.b = ...; // phase B current [A]
33+
c.c = ...; // phase C current [A] (set to 0 if not measured)
34+
return c;
35+
}
36+
```
37+
38+
You can also provide an optional initialization callback:
39+
40+
```cpp
41+
void initCurrentSense(){
42+
// Configure ADCs, GPIOs, or any hardware setup
43+
}
44+
```
45+
46+
## Step 2. Instantiate `GenericCurrentSense`
47+
48+
```cpp
49+
// GenericCurrentSense constructor
50+
// - readCallback pointer to the function reading phase currents
51+
// - initCallback pointer to the optional init function
52+
GenericCurrentSense current_sense = GenericCurrentSense(readCurrentSense, initCurrentSense);
53+
```
54+
55+
If you prefer, you can also assign callbacks after construction:
56+
57+
```cpp
58+
GenericCurrentSense current_sense;
59+
current_sense.readCallback = readCurrentSense;
60+
current_sense.initCallback = initCurrentSense;
61+
```
62+
63+
## Step 3. Use as a standalone current sensor
64+
65+
Once initialized, you can read phase currents and DC current directly:
66+
67+
```cpp
68+
current_sense.init();
69+
70+
PhaseCurrent_s currents = current_sense.getPhaseCurrents();
71+
float current_magnitude = current_sense.getDCCurrent();
72+
73+
Serial.print(currents.a);
74+
Serial.print("\t");
75+
Serial.print(currents.b);
76+
Serial.print("\t");
77+
Serial.print(currents.c);
78+
Serial.print("\t");
79+
Serial.println(current_magnitude);
80+
```
81+
82+
<blockquote markdown="1" class="info">
83+
<p class="heading" markdown="1">Offset calibration</p>
84+
`GenericCurrentSense::init()` automatically runs a zero-offset calibration by sampling your callback multiple times. Make sure the motor is not driven during initialization.
85+
</blockquote>
86+
87+
## Step 4. Use with FOC control
88+
89+
To use current sensing for torque control (dc_current or foc_current), link it to the motor and driver:
90+
91+
```cpp
92+
// Driver and motor
93+
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 10, 11, 8);
94+
BLDCMotor motor = BLDCMotor(7);
95+
96+
void setup() {
97+
Serial.begin(115200);
98+
99+
// Driver init
100+
driver.voltage_power_supply = 12;
101+
driver.init();
102+
motor.linkDriver(&driver);
103+
104+
// Current sense init and link
105+
current_sense.init();
106+
current_sense.linkDriver(&driver);
107+
motor.linkCurrentSense(&current_sense);
108+
109+
// Select torque control mode
110+
motor.torque_controller = TorqueControlType::foc_current;
111+
// or TorqueControlType::dc_current
112+
113+
motor.init();
114+
motor.initFOC();
115+
}
116+
117+
void loop() {
118+
motor.loopFOC();
119+
motor.move();
120+
}
121+
```
122+
123+
## Tips and troubleshooting
124+
125+
- **Units matter**: your callback must return currents in **amps**.
126+
- **Only two shunts?** Set one of the phases to `0` and the library will estimate it.
127+
- **Phase inversion**: if a phase appears inverted, you can flip it:
128+
```cpp
129+
current_sense.gain_a *= -1; // or gain_b / gain_c
130+
```
131+
- **Alignment**: `initFOC()` will not run the alignment for this sensor type, so make sure your callback returns correct angles from the start.
132+
133+
## Example: Generic current sensing test
134+
135+
```cpp
136+
#include <SimpleFOC.h>
137+
138+
PhaseCurrent_s readCurrentSense(){
139+
PhaseCurrent_s c;
140+
c.a = analogRead(A0);
141+
c.b = analogRead(A1);
142+
c.c = analogRead(A2);
143+
return c;
144+
}
145+
146+
void initCurrentSense(){
147+
pinMode(A0, INPUT);
148+
pinMode(A1, INPUT);
149+
pinMode(A2, INPUT);
150+
}
151+
152+
GenericCurrentSense current_sense = GenericCurrentSense(readCurrentSense, initCurrentSense);
153+
154+
void setup() {
155+
Serial.begin(115200);
156+
current_sense.init();
157+
Serial.println("Current sense ready");
158+
}
159+
160+
void loop() {
161+
PhaseCurrent_s currents = current_sense.getPhaseCurrents();
162+
float current_magnitude = current_sense.getDCCurrent();
163+
164+
Serial.print(currents.a);
165+
Serial.print("\t");
166+
Serial.print(currents.b);
167+
Serial.print("\t");
168+
Serial.print(currents.c);
169+
Serial.print("\t");
170+
Serial.println(current_magnitude);
171+
}
172+
```

docs/simplefoc_library/code/current_sense/index.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ Arduino <span class="simple">Simple<span class="foc">FOC</span>library</span> ha
1616
- [In-line current sensing](inline_current_sense)
1717
- [Low-side current sensing](low_side_current_sense)
1818
- [High-side current sensing](high_side_current_sense) - *Not supported yet*
19+
- [Generic current sensing](generic_current_sense) - for custom current sensing implementations
1920

2021

2122
<img src="extras/Images/comparison_cs.png" class="width40">
2223

23-
up to this moment ( [check the releases <i class="fa fa-tag"></i>](https://github.com/simplefoc/Arduino-FOC/releases) ), Arduino <span class="simple">Simple<span class="foc">FOC</span>library</span> 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).
24+
up to this moment ( [check the releases <i class="fa fa-tag"></i>](https://github.com/simplefoc/Arduino-FOC/releases) ), Arduino <span class="simple">Simple<span class="foc">FOC</span>library</span> supports in-line and low-side current sensing on a wide range of platforms. The generic current sensing method allows you to use any custom current sensing method by providing callbacks to read the currents, without needing to create a new class.
2425

2526
Each one of the current sensing classes will implement all the necessary functionalities for simple and robust implementation of FOC algorithm:
2627
- Hardware config
@@ -33,8 +34,8 @@ Each one of the current sensing classes will implement all the necessary functio
3334
- Calculation of the current vector magnitude
3435
- Calculation of the FOC D and Q currents
3536

36-
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 <span class="simple">Simple<span class="foc">FOC</span>library</span>, see example codes in `utils > current_sense_test`.
37-
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.
37+
Each of the implemented classes can be used as stand-alone classes and they can be used to read current values on BLDC or Stepper driver outputs out of scope of the Arduino <span class="simple">Simple<span class="foc">FOC</span>library</span>, see example codes in `utils > current_sense_test`.
38+
In order for FOC algorithm to work the current sense classes are linked to a `BLDCMotor`, `StepperMotor` or `HybridStepperMotor` class which uses the driver to read the FOC currents.
3839

3940
## 🎯 Our implementation goals
4041
The current sense code will be written in a way to support as many different drivers out there as possible and in a way to be fully interchangeable. Due to the very hardware specific implementations of the ADC acquisition for different MCU architectures and due to very different driver/adc synchronisation requirements for different current sensing approaches this task is probably one of the most complex challenges for the <span class="simple">Simple<span class="foc">FOC</span>library</span> so far. Therefore the work will be done in iterations and each release will better and better support. Please make sure to follow out github and [check the releases <i class="fa fa-tag"></i>](https://github.com/simplefoc/Arduino-FOC/releases).
@@ -48,12 +49,12 @@ MCU | In-line | Low-side | High-side
4849
Arduino (8-bit) | ✔️ | ❌ | ❌
4950
Arduino DUE | ✔️ | ❌ | ❌
5051
stm32 (in general) | ✔️ | ❌ | ❌
51-
stm32f1 family | ✔️ | ✔️ (one motor) | ❌
52-
stm32f4 family | ✔️ | ✔️ (one motor) | ❌
53-
stm32g4 family | ✔️ | ✔️ (one motor) | ❌
54-
stm32l4 family | ✔️ | ✔️ (one motor) | ❌
55-
stm32f7 family | ✔️ | ✔️ (one motor) | ❌
56-
stm32h7 family | ✔️ | ✔️ (one motor) | ❌
52+
stm32f1 family | ✔️ | ✔️ | ❌
53+
stm32f4 family | ✔️ | ✔️ | ❌
54+
stm32g4 family | ✔️ | ✔️ | ❌
55+
stm32l4 family | ✔️ | ✔️ | ❌
56+
stm32f7 family | ✔️ | ✔️ | ❌
57+
stm32h7 family | ✔️ | ✔️ | ❌
5758
stm32 B_G431B_ESC1 | ❌ | ✔️ (one motor) | ❌
5859
esp32/esp32s3 | ✔️ | ✔️ | ❌
5960
esp32s2/esp32c3 | ✔️ | ❌ | ❌
@@ -66,9 +67,12 @@ Raspberry Pi Pico | ✔️ | ❌ | ❌
6667
Portenta H7 | ✔️ | ❌ | ❌
6768
nRF52 | ✔️ | ❌ | ❌
6869
Renesas (UNO R4) | ❌ | ❌ | ❌
70+
Arduino Nano Matter(📢NEW) | ✔️ | ✔️ (one motor) | ✔️ (not tested)
6971

7072
Note: current sensing on Renesas MCUs will be added in a future release.
7173

7274
## Digging deeper
7375

74-
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).
76+
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.
77+
78+
[Learn about current sensing theory and implementation](digging_deeper){: .btn .btn-docs}

docs/simplefoc_library/code/current_sense/inline.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Teensy | ✔️
4141
Raspberry Pi Pico | ✔️
4242
Portenta H7 | ✔️
4343
Renesas (UNO R4) | ❌ (TBD)
44+
Arduino Nano Matter(📢NEW) | ✔️
4445

4546

4647

@@ -59,7 +60,7 @@ To instantiate the inline current sensor using the <span class="simple">Simple<s
5960
// - phA - A phase adc pin
6061
// - phB - B phase adc pin
6162
// - phC - C phase adc pin (optional)
62-
InlineCurrentSense current_sense = InlineCurrentSense(0.01, 20, A0, A1, A2);
63+
InlineCurrentSense current_sense = InlineCurrentSense(0.01f, 20.0f, A0, A1, A2);
6364
```
6465

6566
This class takes as a parameter either 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.
@@ -75,7 +76,7 @@ Alternatively `InlineCurrentSense` can be created by specifying the mV per Amp r
7576
// - phA - A phase adc pin
7677
// - phB - B phase adc pin
7778
// - phC - C phase adc pin (optional)
78-
InlineCurrentSense current_sense = InlineCurrentSense(66.0, A0, A1, A2);
79+
InlineCurrentSense current_sense = InlineCurrentSense(66.0f, A0, A1, A2);
7980
```
8081

8182
### Measuring 2 out of 3 currents

0 commit comments

Comments
 (0)