Skip to content

Commit c1509d0

Browse files
committed
init v2.0.2
1 parent e86c199 commit c1509d0

File tree

174 files changed

+8918
-3516
lines changed

Some content is hidden

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

174 files changed

+8918
-3516
lines changed

library_source/BLDCMotor.cpp

Lines changed: 110 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,39 @@
11
#include "BLDCMotor.h"
22

3-
// BLDCMotor( int phA, int phB, int phC, int pp, int cpr, int en)
3+
// // BLDCMotor( int phA, int phB, int phC, int pp, int cpr, int en)
4+
// // - phA, phB, phC - motor A,B,C phase pwm pins
5+
// // - pp - pole pair number
6+
// // - cpr - counts per rotation number (cpm=ppm*4)
7+
// // - enable pin - (optional input)
8+
// BLDCMotor::BLDCMotor( int phA, int phB, int phC, int pp, int cpr, int en){
9+
// noop;
10+
// }
11+
12+
// BLDCMotor( int pp)
413
// - phA, phB, phC - motor A,B,C phase pwm pins
514
// - pp - pole pair number
615
// - cpr - counts per rotation number (cpm=ppm*4)
716
// - enable pin - (optional input)
8-
BLDCMotor::BLDCMotor(int phA, int phB, int phC, int pp, int en)
17+
BLDCMotor::BLDCMotor(int pp)
918
: FOCMotor()
1019
{
11-
// Pin initialization
12-
pwmA = phA;
13-
pwmB = phB;
14-
pwmC = phC;
20+
// save pole pairs number
1521
pole_pairs = pp;
22+
}
1623

17-
// enable_pin pin
18-
enable_pin = en;
1924

25+
/**
26+
Link the driver which controls the motor
27+
*/
28+
void BLDCMotor::linkDriver(BLDCDriver* _driver) {
29+
driver = _driver;
2030
}
2131

22-
2332
// init hardware pins
24-
void BLDCMotor::init(long pwm_frequency) {
25-
if(monitor_port) monitor_port->println("MOT: Init pins.");
26-
// PWM pins
27-
pinMode(pwmA, OUTPUT);
28-
pinMode(pwmB, OUTPUT);
29-
pinMode(pwmC, OUTPUT);
30-
if(enable_pin != NOT_SET) pinMode(enable_pin, OUTPUT);
31-
32-
if(monitor_port) monitor_port->println("MOT: PWM config.");
33-
// Increase PWM frequency to 32 kHz
34-
// make silent
35-
_setPwmFrequency(pwm_frequency, pwmA, pwmB, pwmC);
36-
33+
void BLDCMotor::init() {
34+
if(monitor_port) monitor_port->println("MOT: Initialise variables.");
3735
// sanity check for the voltage limit configuration
38-
if(voltage_limit > voltage_power_supply) voltage_limit = voltage_power_supply;
36+
if(voltage_limit > driver->voltage_limit) voltage_limit = driver->voltage_limit;
3937
// constrain voltage for sensor alignment
4038
if(voltage_sensor_align > voltage_limit) voltage_sensor_align = voltage_limit;
4139
// update the controller limits
@@ -44,7 +42,7 @@ void BLDCMotor::init(long pwm_frequency) {
4442

4543
_delay(500);
4644
// enable motor
47-
if(monitor_port) monitor_port->println("MOT: Enable.");
45+
if(monitor_port) monitor_port->println("MOT: Enable driver.");
4846
enable();
4947
_delay(500);
5048
}
@@ -53,18 +51,18 @@ void BLDCMotor::init(long pwm_frequency) {
5351
// disable motor driver
5452
void BLDCMotor::disable()
5553
{
56-
// disable the driver - if enable_pin pin available
57-
if (enable_pin != NOT_SET) digitalWrite(enable_pin, LOW);
5854
// set zero to PWM
59-
setPwm(0, 0, 0);
55+
driver->setPwm(0, 0, 0);
56+
// disable the driver
57+
driver->disable();
6058
}
6159
// enable motor driver
6260
void BLDCMotor::enable()
6361
{
62+
// enable the driver
63+
driver->enable();
6464
// set zero to PWM
65-
setPwm(0, 0, 0);
66-
// enable_pin the driver - if enable_pin pin available
67-
if (enable_pin != NOT_SET) digitalWrite(enable_pin, HIGH);
65+
driver->setPwm(0, 0, 0);
6866

6967
}
7068

@@ -100,13 +98,13 @@ int BLDCMotor::alignSensor() {
10098
float start_angle = shaftAngle();
10199
for (int i = 0; i <=5; i++ ) {
102100
float angle = _3PI_2 + _2PI * i / 6.0;
103-
setPhaseVoltage(voltage_sensor_align, angle);
101+
setPhaseVoltage(voltage_sensor_align, 0, angle);
104102
_delay(200);
105103
}
106104
float mid_angle = shaftAngle();
107105
for (int i = 5; i >=0; i-- ) {
108106
float angle = _3PI_2 + _2PI * i / 6.0;
109-
setPhaseVoltage(voltage_sensor_align, angle);
107+
setPhaseVoltage(voltage_sensor_align, 0, angle);
110108
_delay(200);
111109
}
112110
if (mid_angle < start_angle) {
@@ -121,7 +119,7 @@ int BLDCMotor::alignSensor() {
121119
// set sensor to zero
122120
sensor->initRelativeZero();
123121
_delay(500);
124-
setPhaseVoltage(0,0);
122+
setPhaseVoltage(0, 0, 0);
125123
_delay(200);
126124

127125
// find the index if available
@@ -153,7 +151,7 @@ int BLDCMotor::absoluteZeroAlign() {
153151
}
154152
voltage_q = 0;
155153
// disable motor
156-
setPhaseVoltage(0,0);
154+
setPhaseVoltage(0, 0, 0);
157155

158156
// align absolute zero if it has been found
159157
if(!sensor->needsAbsoluteZeroSearch()){
@@ -172,7 +170,7 @@ void BLDCMotor::loopFOC() {
172170
// shaft angle
173171
shaft_angle = shaftAngle();
174172
// set the phase voltage - FOC heart function :)
175-
setPhaseVoltage(voltage_q, _electricalAngle(shaft_angle,pole_pairs));
173+
setPhaseVoltage(voltage_q, voltage_d, _electricalAngle(shaft_angle,pole_pairs));
176174
}
177175

178176
// Iterative function running outer loop of the FOC algorithm
@@ -219,30 +217,85 @@ void BLDCMotor::move(float new_target) {
219217
}
220218

221219

222-
// Method using FOC to set Uq to the motor at the optimal angle
220+
// Method using FOC to set Uq and Ud to the motor at the optimal angle
223221
// Function implementing Space Vector PWM and Sine PWM algorithms
224222
//
225223
// Function using sine approximation
226224
// regular sin + cos ~300us (no memory usaage)
227225
// approx _sin + _cos ~110us (400Byte ~ 20% of memory)
228-
void BLDCMotor::setPhaseVoltage(float Uq, float angle_el) {
226+
void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
227+
228+
const bool centered = true;
229+
int sector;
230+
float _ca,_sa;
231+
229232
switch (foc_modulation)
230233
{
234+
case FOCModulationType::Trapezoid_120 :
235+
// see https://www.youtube.com/watch?v=InzXA7mWBWE Slide 5
236+
static int trap_120_map[6][3] = {
237+
{0,1,-1},{-1,1,0},{-1,0,1},{0,-1,1},{1,-1,0},{1,0,-1} // each is 60 degrees with values for 3 phases of 1=positive -1=negative 0=high-z
238+
};
239+
// static int trap_120_state = 0;
240+
sector = 6 * (_normalizeAngle(angle_el + PI/6.0 + zero_electric_angle) / _2PI); // adding PI/6 to align with other modes
241+
242+
Ua = Uq + trap_120_map[sector][0] * Uq;
243+
Ub = Uq + trap_120_map[sector][1] * Uq;
244+
Uc = Uq + trap_120_map[sector][2] * Uq;
245+
246+
if (centered) {
247+
Ua += (driver->voltage_limit)/2 -Uq;
248+
Ub += (driver->voltage_limit)/2 -Uq;
249+
Uc += (driver->voltage_limit)/2 -Uq;
250+
}
251+
break;
252+
253+
case FOCModulationType::Trapezoid_150 :
254+
// see https://www.youtube.com/watch?v=InzXA7mWBWE Slide 8
255+
static int trap_150_map[12][3] = {
256+
{0,1,-1},{-1,1,-1},{-1,1,0},{-1,1,1},{-1,0,1},{-1,-1,1},{0,-1,1},{1,-1,1},{1,-1,0},{1,-1,-1},{1,0,-1},{1,1,-1} // each is 30 degrees with values for 3 phases of 1=positive -1=negative 0=high-z
257+
};
258+
// static int trap_150_state = 0;
259+
sector = 12 * (_normalizeAngle(angle_el + PI/6.0 + zero_electric_angle) / _2PI); // adding PI/6 to align with other modes
260+
261+
Ua = Uq + trap_150_map[sector][0] * Uq;
262+
Ub = Uq + trap_150_map[sector][1] * Uq;
263+
Uc = Uq + trap_150_map[sector][2] * Uq;
264+
265+
//center
266+
if (centered) {
267+
Ua += (driver->voltage_limit)/2 -Uq;
268+
Ub += (driver->voltage_limit)/2 -Uq;
269+
Uc += (driver->voltage_limit)/2 -Uq;
270+
}
271+
272+
break;
273+
231274
case FOCModulationType::SinePWM :
232275
// Sinusoidal PWM modulation
233276
// Inverse Park + Clarke transformation
234277

235278
// angle normalization in between 0 and 2pi
236279
// only necessary if using _sin and _cos - approximation functions
237280
angle_el = _normalizeAngle(angle_el + zero_electric_angle);
281+
_ca = _cos(angle_el);
282+
_sa = _sin(angle_el);
238283
// Inverse park transform
239-
Ualpha = -_sin(angle_el) * Uq; // -sin(angle) * Uq;
240-
Ubeta = _cos(angle_el) * Uq; // cos(angle) * Uq;
284+
Ualpha = _ca * Ud - _sa * Uq; // -sin(angle) * Uq;
285+
Ubeta = _sa * Ud + _ca * Uq; // cos(angle) * Uq;
241286

242287
// Clarke transform
243-
Ua = Ualpha + voltage_power_supply/2;
244-
Ub = -0.5 * Ualpha + _SQRT3_2 * Ubeta + voltage_power_supply/2;
245-
Uc = -0.5 * Ualpha - _SQRT3_2 * Ubeta + voltage_power_supply/2;
288+
Ua = Ualpha + driver->voltage_limit/2;
289+
Ub = -0.5 * Ualpha + _SQRT3_2 * Ubeta + driver->voltage_limit/2;
290+
Uc = -0.5 * Ualpha - _SQRT3_2 * Ubeta + driver->voltage_limit/2;
291+
292+
if (!centered) {
293+
float Umin = min(Ua, min(Ub, Uc));
294+
Ua -= Umin;
295+
Ub -= Umin;
296+
Uc -= Umin;
297+
}
298+
246299
break;
247300

248301
case FOCModulationType::SpaceVectorPWM :
@@ -259,15 +312,15 @@ void BLDCMotor::setPhaseVoltage(float Uq, float angle_el) {
259312
angle_el = _normalizeAngle(angle_el + zero_electric_angle + _PI_2);
260313

261314
// find the sector we are in currently
262-
int sector = floor(angle_el / _PI_3) + 1;
315+
sector = floor(angle_el / _PI_3) + 1;
263316
// calculate the duty cycles
264-
float T1 = _SQRT3*_sin(sector*_PI_3 - angle_el) * Uq/voltage_power_supply;
265-
float T2 = _SQRT3*_sin(angle_el - (sector-1.0)*_PI_3) * Uq/voltage_power_supply;
317+
float T1 = _SQRT3*_sin(sector*_PI_3 - angle_el) * Uq/driver->voltage_limit;
318+
float T2 = _SQRT3*_sin(angle_el - (sector-1.0)*_PI_3) * Uq/driver->voltage_limit;
266319
// two versions possible
267-
// centered around voltage_power_supply/2
268-
float T0 = 1 - T1 - T2;
269-
// pulled to 0 - better for low power supply voltage
270-
//float T0 = 0;
320+
float T0 = 0; // pulled to 0 - better for low power supply voltage
321+
if (centered) {
322+
T0 = 1 - T1 - T2; //centered around driver->voltage_limit/2
323+
}
271324

272325
// calculate the duty cycles(times)
273326
float Ta,Tb,Tc;
@@ -310,27 +363,15 @@ void BLDCMotor::setPhaseVoltage(float Uq, float angle_el) {
310363
}
311364

312365
// calculate the phase voltages and center
313-
Ua = Ta*voltage_power_supply;
314-
Ub = Tb*voltage_power_supply;
315-
Uc = Tc*voltage_power_supply;
366+
Ua = Ta*driver->voltage_limit;
367+
Ub = Tb*driver->voltage_limit;
368+
Uc = Tc*driver->voltage_limit;
316369
break;
370+
317371
}
318372

319-
// set the voltages in hardware
320-
setPwm(Ua, Ub, Uc);
321-
}
322-
323-
324-
325-
// Set voltage to the pwm pin
326-
void BLDCMotor::setPwm(float Ua, float Ub, float Uc) {
327-
// calculate duty cycle
328-
// limited in [0,1]
329-
float dc_a = constrain(Ua / voltage_power_supply, 0 , 1 );
330-
float dc_b = constrain(Ub / voltage_power_supply, 0 , 1 );
331-
float dc_c = constrain(Uc / voltage_power_supply, 0 , 1 );
332-
// hardware specific writing
333-
_writeDutyCycle(dc_a, dc_b, dc_c, pwmA, pwmB, pwmC );
373+
// set the voltages in driver
374+
driver->setPwm(Ua, Ub, Uc);
334375
}
335376

336377

@@ -348,7 +389,7 @@ void BLDCMotor::velocityOpenloop(float target_velocity){
348389
shaft_angle += target_velocity*Ts;
349390

350391
// set the maximal allowed voltage (voltage_limit) with the necessary angle
351-
setPhaseVoltage(voltage_limit, _electricalAngle(shaft_angle, pole_pairs));
392+
setPhaseVoltage(voltage_limit, 0, _electricalAngle(shaft_angle, pole_pairs));
352393

353394
// save timestamp for next call
354395
open_loop_timestamp = now_us;
@@ -371,7 +412,7 @@ void BLDCMotor::angleOpenloop(float target_angle){
371412
shaft_angle = target_angle;
372413

373414
// set the maximal allowed voltage (voltage_limit) with the necessary angle
374-
setPhaseVoltage(voltage_limit, _electricalAngle(shaft_angle, pole_pairs));
415+
setPhaseVoltage(voltage_limit, 0, _electricalAngle(shaft_angle, pole_pairs));
375416

376417
// save timestamp for next call
377418
open_loop_timestamp = now_us;

0 commit comments

Comments
 (0)