SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
BLDCMotor.cpp
Go to the documentation of this file.
1#include "BLDCMotor.h"
3
4
5// see https://www.youtube.com/watch?v=InzXA7mWBWE Slide 5
6// each is 60 degrees with values for 3 phases of 1=positive -1=negative 0=high-z
7int trap_120_map[6][3] = {
8 {_HIGH_IMPEDANCE,1,-1},
9 {-1,1,_HIGH_IMPEDANCE},
10 {-1,_HIGH_IMPEDANCE,1},
11 {_HIGH_IMPEDANCE,-1,1},
12 {1,-1,_HIGH_IMPEDANCE},
13 {1,_HIGH_IMPEDANCE,-1}
14};
15
16// see https://www.youtube.com/watch?v=InzXA7mWBWE Slide 8
17// each is 30 degrees with values for 3 phases of 1=positive -1=negative 0=high-z
18int trap_150_map[12][3] = {
19 {_HIGH_IMPEDANCE,1,-1},
20 {-1,1,-1},
21 {-1,1,_HIGH_IMPEDANCE},
22 {-1,1,1},
23 {-1,_HIGH_IMPEDANCE,1},
24 {-1,-1,1},
25 {_HIGH_IMPEDANCE,-1,1},
26 {1,-1,1},
27 {1,-1,_HIGH_IMPEDANCE},
28 {1,-1,-1},
29 {1,_HIGH_IMPEDANCE,-1},
30 {1,1,-1}
31};
32
33// BLDCMotor( int pp , float R)
34// - pp - pole pair number
35// - R - motor phase resistance
36// - KV - motor kv rating (rmp/v)
37// - Lq - motor q-axis inductance [H]
38// - Ld - motor d-axis inductance [H]
39BLDCMotor::BLDCMotor(int pp, float _R, float _KV, float _Lq, float _Ld)
40: FOCMotor()
41{
42 // save pole pairs number
43 pole_pairs = pp;
44 // save phase resistance number
46 // save back emf constant KV = 1/KV
47 // 1/sqrt(3) - rms value
48 KV_rating = _KV;
49 // save phase inductance
50 axis_inductance = {_Ld, _Lq};
51 phase_inductance = _Lq; // FOR BACKWARDS COMPATIBILITY
52
53 // torque control type is voltage by default
55}
56
57
58/**
59 Link the driver which controls the motor
60*/
62 driver = _driver;
63}
64
65// init hardware pins
67 if (!driver || !driver->initialized) {
69 SIMPLEFOC_MOTOR_ERROR("Init not possible, driver not init");
70 return 0;
71 }
74
75 // sanity check for the voltage limit configuration
77 // constrain voltage for sensor alignment
79
80 // update limits in the motor controllers
84
86 // if only single inductance value is set, use it for both d and q axis
88 }
89
90 // if using open loop control, set a CW as the default direction if not already set
91 // only if no sensor is used
92 if(!sensor){
97 }
98 }
99
100 _delay(500);
101 // enable motor
102 SIMPLEFOC_MOTOR_DEBUG("Enable driver.");
103 enable();
104 _delay(500);
106 return 1;
107}
108
109
110// disable motor driver
112{
113 // disable the current sense
115 // set zero to PWM
116 driver->setPwm(0, 0, 0);
117 // disable the driver
118 driver->disable();
119 // motor status update
120 enabled = 0;
121}
122// enable motor driver
124{
125 // enable the driver
126 driver->enable();
127 // set zero to PWM
128 driver->setPwm(0, 0, 0);
129 // enable the current sense
131 // reset the pids
133 P_angle.reset();
136 // motor status update
137 enabled = 1;
138}
139
140/**
141 FOC functions
142*/
143
144float BLDCMotor::estimateBEMF(float vel){
145 // bemf constant is approximately 1/KV rating
146 // V_bemf = K_bemf * velocity
147 return vel/(KV_rating*_SQRT3)/_RPM_TO_RADS;
148}
149
150
151// Method using FOC to set Uq and Ud to the motor at the optimal angle
152// Function implementing Space Vector PWM, Sine PWM and Trapezoidal commutation algorithms
153void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
154
155 float center;
156 int sector;
157 float _ca,_sa;
158
159 switch (foc_modulation)
160 {
162 // see https://www.youtube.com/watch?v=InzXA7mWBWE Slide 5
163 // determine the sector
164 sector = 6 * (_normalizeAngle(angle_el + _PI_6 ) / _2PI); // adding PI/6 to align with other modes
165 // centering the voltages around either
166 // modulation_centered == true > driver.voltage_limit/2
167 // modulation_centered == false > or Adaptable centering, all phases drawn to 0 when Uq=0
168 center = modulation_centered ? (driver->voltage_limit)/2 : Uq;
169
170 if(trap_120_map[sector][0] == _HIGH_IMPEDANCE){
171 Ua= center;
172 Ub = trap_120_map[sector][1] * Uq + center;
173 Uc = trap_120_map[sector][2] * Uq + center;
175 }else if(trap_120_map[sector][1] == _HIGH_IMPEDANCE){
176 Ua = trap_120_map[sector][0] * Uq + center;
177 Ub = center;
178 Uc = trap_120_map[sector][2] * Uq + center;
180 }else{
181 Ua = trap_120_map[sector][0] * Uq + center;
182 Ub = trap_120_map[sector][1] * Uq + center;
183 Uc = center;
185 }
186
187 break;
188
190 // see https://www.youtube.com/watch?v=InzXA7mWBWE Slide 8
191 // determine the sector
192 sector = 12 * (_normalizeAngle(angle_el + _PI_6 ) / _2PI); // adding PI/6 to align with other modes
193 // centering the voltages around either
194 // modulation_centered == true > driver.voltage_limit/2
195 // modulation_centered == false > or Adaptable centering, all phases drawn to 0 when Uq=0
196 center = modulation_centered ? (driver->voltage_limit)/2 : Uq;
197
198 if(trap_150_map[sector][0] == _HIGH_IMPEDANCE){
199 Ua= center;
200 Ub = trap_150_map[sector][1] * Uq + center;
201 Uc = trap_150_map[sector][2] * Uq + center;
203 }else if(trap_150_map[sector][1] == _HIGH_IMPEDANCE){
204 Ua = trap_150_map[sector][0] * Uq + center;
205 Ub = center;
206 Uc = trap_150_map[sector][2] * Uq + center;
208 }else if(trap_150_map[sector][2] == _HIGH_IMPEDANCE){
209 Ua = trap_150_map[sector][0] * Uq + center;
210 Ub = trap_150_map[sector][1] * Uq + center;
211 Uc = center;
213 }else{
214 Ua = trap_150_map[sector][0] * Uq + center;
215 Ub = trap_150_map[sector][1] * Uq + center;
216 Uc = trap_150_map[sector][2] * Uq + center;
218 }
219
220 break;
221
224
225 // Sinusoidal PWM modulation
226 // Inverse Park + Clarke transformation
227 _sincos(angle_el, &_sa, &_ca);
228
229 // Inverse park transform
230 Ualpha = _ca * Ud - _sa * Uq; // -sin(angle) * Uq;
231 Ubeta = _sa * Ud + _ca * Uq; // cos(angle) * Uq;
232
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
247 center = driver->voltage_limit/2;
249 // discussed here: https://community.simplefoc.com/t/embedded-world-2023-stm32-cordic-co-processor/3107/165?u=candas1
250 // a bit more info here: https://microchipdeveloper.com/mct5001:which-zsm-is-best
251 // Midpoint Clamp
252 float Umin = min(Ua, min(Ub, Uc));
253 float Umax = max(Ua, max(Ub, Uc));
254 center -= (Umax+Umin) / 2;
255 }
256 Ua += center;
257 Ub += center;
258 Uc += center;
259 }else{
260 float Umin = min(Ua, min(Ub, Uc));
261 Ua -= Umin;
262 Ub -= Umin;
263 Uc -= Umin;
264 }
265 break;
266 }
267
268 // set the voltages in driver
269 driver->setPwm(Ua, Ub, Uc);
270}
int trap_120_map[6][3]
Definition BLDCMotor.cpp:7
int trap_150_map[12][3]
Definition BLDCMotor.cpp:18
@ PHASE_ON
Definition FOCDriver.h:9
@ PHASE_OFF
Definition FOCDriver.h:8
@ velocity_openloop
Definition FOCMotor.h:53
@ angle_openloop
Definition FOCMotor.h:54
#define SIMPLEFOC_MOTOR_DEBUG(msg,...)
Definition FOCMotor.h:27
@ Trapezoid_120
Definition FOCMotor.h:75
@ SpaceVectorPWM
Space vector modulation method.
Definition FOCMotor.h:74
@ Trapezoid_150
Definition FOCMotor.h:76
@ SinePWM
Sinusoidal PWM modulation.
Definition FOCMotor.h:73
@ motor_uncalibrated
Motor is initialized, but not calibrated (open loop possible)
Definition FOCMotor.h:84
@ motor_initializing
Motor intiialization is in progress.
Definition FOCMotor.h:83
@ motor_init_failed
Motor initialization failed (not recoverable)
Definition FOCMotor.h:89
#define SIMPLEFOC_MOTOR_ERROR(msg,...)
Definition FOCMotor.h:23
@ voltage
Torque control using voltage.
Definition FOCMotor.h:63
@ UNKNOWN
Definition Sensor.h:12
@ CW
Definition Sensor.h:10
virtual void setPhaseState(PhaseState sa, PhaseState sb, PhaseState sc)=0
virtual void setPwm(float Ua, float Ub, float Uc)=0
void disable() override
void setPhaseVoltage(float Uq, float Ud, float angle_el) override
float Ub
Definition BLDCMotor.h:37
BLDCDriver * driver
BLDCDriver instance.
Definition BLDCMotor.h:39
int init() override
Definition BLDCMotor.cpp:66
float Ua
Definition BLDCMotor.h:37
void enable() override
virtual void linkDriver(BLDCDriver *driver)
Definition BLDCMotor.cpp:61
BLDCMotor(int pp, float R=NOT_SET, float KV=NOT_SET, float L_q=NOT_SET, float L_d=NOT_SET)
Definition BLDCMotor.cpp:39
float Uc
Current phase voltages Ua,Ub and Uc set to motor.
Definition BLDCMotor.h:37
float estimateBEMF(float velocity) override
virtual void enable()
virtual void disable()
virtual void enable()=0
virtual void disable()=0
bool initialized
true if driver was successfully initialized
Definition FOCDriver.h:39
float voltage_limit
limiting voltage set to the motor
Definition FOCDriver.h:37
int8_t enabled
enabled or disabled motor flag
Definition FOCMotor.h:243
void updateCurrentLimit(float new_current_limit)
Definition FOCMotor.cpp:453
int8_t modulation_centered
flag (1) centered modulation around driver limit /2 or (0) pulled to 0
Definition FOCMotor.h:248
DQ_s axis_inductance
motor direct axis phase inductance
Definition FOCMotor.h:235
PIDController PID_current_q
parameter determining the q current PID config
Definition FOCMotor.h:256
float Ualpha
Definition FOCMotor.h:221
void updateVoltageLimit(float new_voltage_limit)
Definition FOCMotor.cpp:466
MotionControlType controller
parameter determining the control loop to be used
Definition FOCMotor.h:253
float phase_resistance
motor phase resistance
Definition FOCMotor.h:231
PIDController PID_current_d
parameter determining the d current PID config
Definition FOCMotor.h:257
Sensor * sensor
CurrentSense link.
Definition FOCMotor.h:300
CurrentSense * current_sense
Definition FOCMotor.h:302
float voltage_limit
Voltage limiting variable - global limit.
Definition FOCMotor.h:238
float velocity_limit
Velocity limiting variable - global limit.
Definition FOCMotor.h:240
PIDController P_angle
parameter determining the position PID configuration
Definition FOCMotor.h:261
FOCMotorStatus motor_status
motor status
Definition FOCMotor.h:244
float Ubeta
Phase voltages U alpha and U beta used for inverse Park and Clarke transform.
Definition FOCMotor.h:221
float KV_rating
motor KV rating
Definition FOCMotor.h:233
float voltage_sensor_align
sensor and motor align voltage parameter
Definition FOCMotor.h:227
Direction sensor_direction
default is CW. if sensor_direction == Direction::CCW then direction will be flipped compared to CW....
Definition FOCMotor.h:270
float current_limit
Current limiting variable - global limit.
Definition FOCMotor.h:239
TorqueControlType torque_controller
parameter determining the torque control type
Definition FOCMotor.h:252
PIDController PID_velocity
parameter determining the velocity PID configuration
Definition FOCMotor.h:260
float phase_inductance
motor phase inductance q axis - FOR BACKWARDS COMPATIBILITY
Definition FOCMotor.h:234
int pole_pairs
motor pole pairs number
Definition FOCMotor.h:232
void updateVelocityLimit(float new_velocity_limit)
Definition FOCMotor.cpp:446
FOCModulationType foc_modulation
parameter determining modulation algorithm
Definition FOCMotor.h:247
void reset()
Definition pid.cpp:66
#define _SQRT3_2
Definition foc_utils.h:23
#define _2PI
Definition foc_utils.h:29
#define _SQRT3
Definition foc_utils.h:21
#define _HIGH_IMPEDANCE
Definition foc_utils.h:35
#define _PI_6
Definition foc_utils.h:31
float _normalizeAngle(float angle)
#define _RPM_TO_RADS
Definition foc_utils.h:32
#define _isset(a)
Definition foc_utils.h:13
void _sincos(float a, float *s, float *c)
float q
Definition foc_utils.h:46
void _delay(unsigned long ms)
Definition time_utils.cpp:5