Skip to content

Commit d73aea5

Browse files
committed
typo + inductance
1 parent 96be937 commit d73aea5

File tree

14 files changed

+233
-130
lines changed

14 files changed

+233
-130
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Therefore this is an attempt to:
3030
- For official driver boards see [<span class="simple">Simple<span class="foc">FOC</span>Boards</span>](https://docs.simplefoc.com/boards)
3131
- Many many more boards developed by the community members, see [<span class="simple">Simple<span class="foc">FOC</span>Community</span>](https://community.simplefoc.com/)
3232

33-
> NEXT RELEASE 📢 : <span class="simple">Simple<span class="foc">FOC</span>library</span> v2.3.6
33+
> NEXT RELEASE 📢 : <span class="simple">Simple<span class="foc">FOC</span>library</span> v2.4.0
3434
>
3535
> - STM32 bugfix
3636
> - BG341 low-side current sense sync was lost in v2.3.5 - fixed [#482](https://github.com/simplefoc/Arduino-FOC/pull/482)

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=Simple FOC
2-
version=2.3.6
2+
version=2.4.0
33
author=Simplefoc <[email protected]>
44
maintainer=Simplefoc <[email protected]>
55
sentence=A library demistifying FOC for BLDC motors

src/BLDCMotor.cpp

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ int trap_150_map[12][3] = {
3535
// - R - motor phase resistance
3636
// - KV - motor kv rating (rmp/v)
3737
// - L - motor phase inductance
38-
BLDCMotor::BLDCMotor(int pp, float _R, float _KV, float _inductance)
38+
BLDCMotor::BLDCMotor(int pp, float _R, float _KV, float _Lq, float _Ld)
3939
: FOCMotor()
4040
{
4141
// save pole pairs number
@@ -46,7 +46,8 @@ BLDCMotor::BLDCMotor(int pp, float _R, float _KV, float _inductance)
4646
// 1/sqrt(3) - rms value
4747
KV_rating = _KV;
4848
// save phase inductance
49-
phase_inductance = _inductance;
49+
phase_inductance_dq = {_Ld, _Lq};
50+
phase_inductance = _Lq; // FOR BACKWARDS COMPATIBILITY
5051

5152
// torque control type is voltage by default
5253
torque_controller = TorqueControlType::voltage;
@@ -64,11 +65,11 @@ void BLDCMotor::linkDriver(BLDCDriver* _driver) {
6465
int BLDCMotor::init() {
6566
if (!driver || !driver->initialized) {
6667
motor_status = FOCMotorStatus::motor_init_failed;
67-
SIMPLEFOC_DEBUG("MOT: Init not possible, driver not initialized");
68+
SIMPLEFOC_MOTOR_ERROR("Init not possible, driver not init");
6869
return 0;
6970
}
7071
motor_status = FOCMotorStatus::motor_initializing;
71-
SIMPLEFOC_DEBUG("MOT: Init");
72+
SIMPLEFOC_MOTOR_DEBUG("Init");
7273

7374
// sanity check for the voltage limit configuration
7475
if(voltage_limit > driver->voltage_limit) voltage_limit = driver->voltage_limit;
@@ -80,6 +81,11 @@ int BLDCMotor::init() {
8081
updateVoltageLimit(voltage_limit);
8182
updateVelocityLimit(velocity_limit);
8283

84+
if(_isset(phase_inductance) && !(_isset(phase_inductance_dq.q))) {
85+
// if only single inductance value is set, use it for both d and q axis
86+
phase_inductance_dq = {phase_inductance, phase_inductance};
87+
}
88+
8389
// if using open loop control, set a CW as the default direction if not already set
8490
// only if no sensor is used
8591
if(!sensor){
@@ -92,7 +98,7 @@ int BLDCMotor::init() {
9298

9399
_delay(500);
94100
// enable motor
95-
SIMPLEFOC_DEBUG("MOT: Enable driver.");
101+
SIMPLEFOC_MOTOR_DEBUG("Enable driver.");
96102
enable();
97103
_delay(500);
98104
motor_status = FOCMotorStatus::motor_uncalibrated;
@@ -214,28 +220,29 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
214220

215221
case FOCModulationType::SinePWM :
216222
case FOCModulationType::SpaceVectorPWM :
217-
// Sinusoidal PWM modulation
218-
// Inverse Park + Clarke transformation
219-
_sincos(angle_el, &_sa, &_ca);
220223

221-
// Inverse park transform
222-
Ualpha = _ca * Ud - _sa * Uq; // -sin(angle) * Uq;
223-
Ubeta = _sa * Ud + _ca * Uq; // cos(angle) * Uq;
224+
if (modulation_centered) {
225+
// Sinusoidal PWM modulation
226+
// Inverse Park + Clarke transformation
227+
_sincos(angle_el, &_sa, &_ca);
224228

225-
// Clarke transform
226-
Ua = Ualpha;
227-
Ub = -0.5f * Ualpha + _SQRT3_2 * Ubeta;
228-
Uc = -0.5f * Ualpha - _SQRT3_2 * Ubeta;
229+
// Inverse park transform
230+
Ualpha = _ca * Ud - _sa * Uq; // -sin(angle) * Uq;
231+
Ubeta = _sa * Ud + _ca * Uq; // cos(angle) * Uq;
229232

230-
// centering the voltages around either
231-
// - centered modulation: around driver.voltage_limit/2
232-
// - non-centered modulation: pulls the lowest voltage to 0
233-
// - Can be useful for low-side current sensing
234-
// in cases where the ADC had long sample time
235-
// - The part of the duty cycle in which all phases are
236-
// off is longer than in centered modulation
237-
// - Both SinePWM and SpaceVectorPWM have the same form for non-centered modulation
238-
if (modulation_centered) {
233+
// Clarke transform
234+
Ua = Ualpha;
235+
Ub = -0.5f * Ualpha + _SQRT3_2 * Ubeta;
236+
Uc = -0.5f * Ualpha - _SQRT3_2 * Ubeta;
237+
238+
// centering the voltages around either
239+
// - centered modulation: around driver.voltage_limit/2
240+
// - non-centered modulation: pulls the lowest voltage to 0
241+
// - Can be useful for low-side current sensing
242+
// in cases where the ADC had long sample time
243+
// - The part of the duty cycle in which all phases are
244+
// off is longer than in centered modulation
245+
// - Both SinePWM and SpaceVectorPWM have the same form for non-centered modulation
239246
center = driver->voltage_limit/2;
240247
if (foc_modulation == FOCModulationType::SpaceVectorPWM){
241248
// discussed here: https://community.simplefoc.com/t/embedded-world-2023-stm32-cordic-co-processor/3107/165?u=candas1
@@ -249,10 +256,41 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
249256
Ub += center;
250257
Uc += center;
251258
}else{
252-
float Umin = min(Ua, min(Ub, Uc));
253-
Ua -= Umin;
254-
Ub -= Umin;
255-
Uc -= Umin;
259+
angle_el = _normalizeAngle(angle_el + _PI_2);
260+
_sincos(angle_el, &_sa, &_ca);
261+
262+
263+
264+
// Inverse park transform
265+
Ualpha = _ca * Uq;//- _sa * Uq; // -sin(angle) * Uq;
266+
Ubeta = _sa * Uq;// + _ca * Uq; // cos(angle) * Uq;
267+
268+
// Clarke transform
269+
270+
// determine the segment I, II, III
271+
if ((angle_el >= 0) && (angle_el < _120_D2R)) {
272+
// section I
273+
Ua = Ualpha + _1_SQRT3 * Ubeta;
274+
Ub = _2_SQRT3 * Ubeta;
275+
Uc = 0;
276+
277+
} else if ((angle_el >= _120_D2R) && (angle_el < (2 * _120_D2R))) {
278+
// section III
279+
Ua = 0;
280+
Ub = _1_SQRT3 * Ubeta - Ualpha;
281+
Uc = -_1_SQRT3 * Ubeta - Ualpha;
282+
283+
} else if ((angle_el >= (2 * _120_D2R)) && (angle_el < (3 * _120_D2R))) {
284+
// section II
285+
Ua = Ualpha - _1_SQRT3 * Ubeta;
286+
Ub = 0;
287+
Uc = - _2_SQRT3 * Ubeta;
288+
}
289+
290+
Ua = Ua*1.5;
291+
Ub = Ub*1.5;
292+
Uc = Uc*1.5;
293+
256294
}
257295
break;
258296
}

src/BLDCMotor.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@ class BLDCMotor: public FOCMotor
1818
public:
1919
/**
2020
BLDCMotor class constructor
21-
@param pp pole pairs number
22-
@param R motor phase resistance - [Ohm]
21+
@param pp pole pairs number
22+
@param R motor phase resistance - [Ohm]
2323
@param KV motor KV rating (1/K_bemf) - rpm/V
24-
@param L motor phase inductance - [H]
24+
@param L_q motor phase inductance - [H]
25+
@param L_d motor direct axis inductance - [H]
2526
*/
26-
BLDCMotor(int pp, float R = NOT_SET, float KV = NOT_SET, float L = NOT_SET);
27+
BLDCMotor(int pp, float R = NOT_SET, float KV = NOT_SET, float L_q = NOT_SET, float L_d = NOT_SET);
2728

2829
/**
2930
* Function linking a motor and a foc driver

src/HybridStepperMotor.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// - R - motor phase resistance
77
// - KV - motor kv rating (rmp/v)
88
// - L - motor phase inductance [H]
9-
HybridStepperMotor::HybridStepperMotor(int pp, float _R, float _KV, float _inductance)
9+
HybridStepperMotor::HybridStepperMotor(int pp, float _R, float _KV, float _Lq, float _Ld)
1010
: FOCMotor()
1111
{
1212
// number od pole pairs
@@ -17,7 +17,9 @@ HybridStepperMotor::HybridStepperMotor(int pp, float _R, float _KV, float _induc
1717
// usually used rms
1818
KV_rating = _KV;
1919
// save phase inductance
20-
phase_inductance = _inductance;
20+
phase_inductance_dq = {_Ld, _Lq};
21+
phase_inductance = _Lq; // FOR BACKWARDS COMPATIBILITY
22+
2123

2224
// torque control type is voltage by default
2325
// current and foc_current not supported yet
@@ -30,7 +32,7 @@ HybridStepperMotor::HybridStepperMotor(int pp, float _R, float _KV, float _induc
3032
void HybridStepperMotor::linkDriver(BLDCDriver *_driver)
3133
{
3234
driver = _driver;
33-
SIMPLEFOC_DEBUG("MOT: BLDCDriver linked, using pin C as the mid-phase");
35+
SIMPLEFOC_MOTOR_DEBUG("BLDCDriver linked, using pin C as the mid-phase");
3436
}
3537

3638
// override of the FOCMotor's current sense linking
@@ -46,12 +48,11 @@ int HybridStepperMotor::init()
4648
if (!driver || !driver->initialized)
4749
{
4850
motor_status = FOCMotorStatus::motor_init_failed;
49-
SIMPLEFOC_DEBUG("MOT: Init not possible, driver not initialized");
51+
SIMPLEFOC_MOTOR_ERROR("Init not possible, driver not init");
5052
return 0;
5153
}
5254
motor_status = FOCMotorStatus::motor_initializing;
53-
SIMPLEFOC_DEBUG("MOT: Init");
54-
55+
SIMPLEFOC_MOTOR_DEBUG("Init");
5556
// sanity check for the voltage limit configuration
5657
if (voltage_limit > driver->voltage_limit)
5758
voltage_limit = driver->voltage_limit;
@@ -64,6 +65,11 @@ int HybridStepperMotor::init()
6465
updateVoltageLimit(voltage_limit);
6566
updateVelocityLimit(velocity_limit);
6667

68+
if(_isset(phase_inductance) && !(_isset(phase_inductance_dq.q))) {
69+
// if only single inductance value is set, use it for both d and q axis
70+
phase_inductance_dq = {phase_inductance, phase_inductance};
71+
}
72+
6773
// if using open loop control, set a CW as the default direction if not already set
6874
// only if no sensor is used
6975
if(!sensor){
@@ -76,7 +82,7 @@ int HybridStepperMotor::init()
7682

7783
_delay(500);
7884
// enable motor
79-
SIMPLEFOC_DEBUG("MOT: Enable driver.");
85+
SIMPLEFOC_MOTOR_DEBUG("Enable driver.");
8086
enable();
8187
_delay(500);
8288

src/HybridStepperMotor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class HybridStepperMotor : public FOCMotor
2727
* @param KV motor KV rating (1/K_bemf) - rpm/V
2828
* @param L motor phase inductance - [H]
2929
*/
30-
HybridStepperMotor(int pp, float R = NOT_SET, float KV = NOT_SET, float L = NOT_SET);
30+
HybridStepperMotor(int pp, float R = NOT_SET, float KV = NOT_SET, float L_q = NOT_SET, float L_d = NOT_SET);
3131

3232
/**
3333
* Function linking a motor and a foc driver

src/StepperMotor.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// - R - motor phase resistance
88
// - KV - motor kv rating (rmp/v)
99
// - L - motor phase inductance [H]
10-
StepperMotor::StepperMotor(int pp, float _R, float _KV, float _inductance)
10+
StepperMotor::StepperMotor(int pp, float _R, float _KV, float _Lq, float _Ld)
1111
: FOCMotor()
1212
{
1313
// number od pole pairs
@@ -18,7 +18,8 @@ StepperMotor::StepperMotor(int pp, float _R, float _KV, float _inductance)
1818
// usually used rms
1919
KV_rating = _KV;
2020
// save phase inductance
21-
phase_inductance = _inductance;
21+
phase_inductance_dq = {_Ld, _Lq};
22+
phase_inductance = _Lq; // FOR BACKWARDS COMPATIBILITY
2223

2324
// torque control type is voltage by default
2425
// current and foc_current not supported yet
@@ -36,11 +37,11 @@ void StepperMotor::linkDriver(StepperDriver* _driver) {
3637
int StepperMotor::init() {
3738
if (!driver || !driver->initialized) {
3839
motor_status = FOCMotorStatus::motor_init_failed;
39-
SIMPLEFOC_DEBUG("MOT: Init not possible, driver not initialized");
40+
SIMPLEFOC_MOTOR_ERROR("Init not possible, driver not init");
4041
return 0;
4142
}
4243
motor_status = FOCMotorStatus::motor_initializing;
43-
SIMPLEFOC_DEBUG("MOT: Init");
44+
SIMPLEFOC_MOTOR_DEBUG("Init");
4445

4546
// sanity check for the voltage limit configuration
4647
if(voltage_limit > driver->voltage_limit) voltage_limit = driver->voltage_limit;
@@ -52,6 +53,12 @@ int StepperMotor::init() {
5253
updateVoltageLimit(voltage_limit);
5354
updateVelocityLimit(velocity_limit);
5455

56+
if(_isset(phase_inductance) && !(_isset(phase_inductance_dq.q))) {
57+
// if only single inductance value is set, use it for both d and q axis
58+
phase_inductance_dq = {phase_inductance, phase_inductance};
59+
}
60+
61+
5562
// if using open loop control, set a CW as the default direction if not already set
5663
// only if no sensor is used
5764
if(!sensor){
@@ -64,7 +71,7 @@ int StepperMotor::init() {
6471

6572
_delay(500);
6673
// enable motor
67-
SIMPLEFOC_DEBUG("MOT: Enable driver.");
74+
SIMPLEFOC_MOTOR_DEBUG("Enable driver.");
6875
enable();
6976
_delay(500);
7077
motor_status = FOCMotorStatus::motor_uncalibrated;

src/StepperMotor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class StepperMotor: public FOCMotor
2727
@param KV motor KV rating (1/K_bemf) - rpm/V
2828
@param L motor phase inductance - [H]
2929
*/
30-
StepperMotor(int pp, float R = NOT_SET, float KV = NOT_SET, float L = NOT_SET);
30+
StepperMotor(int pp, float R = NOT_SET, float KV = NOT_SET, float L_q = NOT_SET, float L_d = NOT_SET);
3131

3232
/**
3333
* Function linking a motor and a foc driver

0 commit comments

Comments
 (0)