Skip to content

Commit e42137b

Browse files
committed
restracturing into a library
1 parent 1f9cc9d commit e42137b

File tree

24 files changed

+807
-145
lines changed

24 files changed

+807
-145
lines changed

.vscode/arduino.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

.vscode/c_cpp_properties.json

Lines changed: 0 additions & 19 deletions
This file was deleted.

examples/MotorFOCExample/Encoder.cpp renamed to Encoder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Encoder::Encoder(int _encA, int _encB , float _cpr, int _index){
2020
cpr = _cpr;
2121
A_active = 0;
2222
B_active = 0;
23+
I_active = 0;
2324
// index pin
2425
index = _index; // its 0 if not used
2526

examples/MotorFOCExample/Encoder.h renamed to Encoder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include "Arduino.h"
55

6+
7+
// Pullup configuation structure
68
enum Pullup{
79
INTERN,
810
EXTERN
@@ -46,6 +48,7 @@ class Encoder{
4648
long pulse_timestamp; // last impulse timestamp in us
4749
float cpr; // impulse cpr
4850
int A_active, B_active; // current active states of A and B line
51+
int I_active; // index active
4952

5053
// velocity calculation varibles
5154
float prev_Th, pulse_per_second;

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
This project is based on widely used in Hobby world brushless gimbal controller HMBGC V2.2.
44
<p>
5-
<img src="./Images/ebay.jpg" height="400px">
6-
<img src="./Images/ebay2.jpg" height="400px">
5+
<img src="extras/Images/ebay.jpg" height="400px">
6+
<img src="extras/Images/ebay2.jpg" height="400px">
77
</p>
88

99
Proper low cost FOC supporting board is very hard to find these days even may not exist. The reason may be that the hobby community has not yet dug into it properly.
@@ -30,9 +30,9 @@ Proper low cost FOC supporting board is very hard to find these days even may no
3030
# Using the library
3131
## Conneciton of encoder and motor
3232
<p>
33-
<img src="./Images/connection.png" height="400px">
34-
<img src="./Images/setup1.jpg" height="400px">
35-
<img src="./Images/pinout.jpg" height="400px">
33+
<img src="extras/Images/connection.png" height="400px">
34+
<img src="extras/Images/setup1.jpg" height="400px">
35+
<img src="extras/Images/pinout.jpg" height="400px">
3636
</p>
3737
To use HMBGC controller for vector control (FOC) you need to connect motor to one of the motor terminals and connect the Encoder. The shema of connection is shown on the figures above, I also took a (very bad) picture of my setup.
3838

@@ -64,18 +64,18 @@ Using the fucntion
6464
motor.setPhaseVoltage(float Uq)
6565
```
6666
you can run BLDC motor as it is DC motor using Park transformation.
67-
<img src="./Images/voltage.png">
67+
<img src="extras/Images/voltage.png">
6868
### Closed loop velocity control
6969
Using the fucntion
7070
```cpp
7171
motor.setVelocity(float v)
7272
```
7373
you can run BLDC motor in closed loop with desired velocity.
74-
<img src="./Images/velocity.png" >
74+
<img src="extras/Images/velocity.png" >
7575
### Closed loop position control
7676
Using the fucntion
7777
```cpp
7878
motor.setPosition(float pos)
7979
```
8080
you can run BLDC motor in closed loop with desired position.
81-
<img src="./Images/position.png">
81+
<img src="extras/Images/position.png">

examples/MotorFOCExample/BLDCMotor.cpp renamed to SimpleFOC.cpp

Lines changed: 39 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "BLDCMotor.h"
1+
#include "SimpleFOC.h"
22

33

44
/*
@@ -20,30 +20,32 @@ BLDCMotor::BLDCMotor(int phA, int phB, int phC, int pp, int en)
2020
// enable_pin pin
2121
enable_pin = en;
2222

23+
// Power supply woltage
24+
power_supply_voltage = DEF_POWER_SUPPLY;
25+
2326
// Velocity loop config
2427
// PI contoroller constant
25-
PI_velocity.K = 0.4;
26-
PI_velocity.Ti = 0.005;
28+
PI_velocity.K = DEF_PI_VEL_K;
29+
PI_velocity.Ti = DEF_PI_VEL_TI;
2730
PI_velocity.timestamp = micros();
31+
PI_velocity.u_limit = DEF_POWER_SUPPLY;
2832

2933
// Ultra slow velocity
3034
// PI contoroller
31-
PI_velocity_ultra_slow.K = 120.0;
32-
PI_velocity_ultra_slow.Ti = 100.0;
35+
PI_velocity_ultra_slow.K = DEF_PI_VEL_US_K;
36+
PI_velocity_ultra_slow.Ti = DEF_PI_VEL_US_TI;
3337
PI_velocity_ultra_slow.timestamp = micros();
38+
PI_velocity_ultra_slow.u_limit = DEF_POWER_SUPPLY;
3439

3540
// position loop config
3641
// P controller constant
37-
P_angle.K = 15;
38-
39-
// Power supply woltage
40-
U_max = 12;
42+
P_angle.K = DEF_P_ANGLE_K;
4143
// maximum angular velocity to be used for positioning
42-
velocity_max = 20;
44+
P_angle.velocity_limit = DEF_P_ANGLE_VEL_LIM;
4345
}
4446

4547
// init hardware pins
46-
void BLDCMotor::init(DriverType type) {
48+
void BLDCMotor::init() {
4749
// PWM pins
4850
pinMode(pwmA, OUTPUT);
4951
pinMode(pwmB, OUTPUT);
@@ -57,7 +59,7 @@ void BLDCMotor::init(DriverType type) {
5759
setPwmFrequency(pwmB);
5860
setPwmFrequency(pwmC);
5961

60-
driver_type = type;
62+
driver = DriverType::bipolar;
6163

6264
delay(500);
6365
}
@@ -107,10 +109,12 @@ void BLDCMotor::linkEncoder(Encoder* enc) {
107109
Encoder alignment to electrical 0 angle
108110
*/
109111
void BLDCMotor::alignEncoder() {
110-
setPhaseVoltage(12, M_PI / 2);
112+
setPhaseVoltage(12, -M_PI/2);
111113
delay(1000);
112114
encoder->setCounterZero();
113-
setPhaseVoltage(0, M_PI / 2);
115+
116+
117+
setPhaseVoltage(0, 0);
114118
}
115119

116120
/**
@@ -131,7 +135,8 @@ float BLDCMotor::electricAngle(float shaftAngle) {
131135
return normalizeAngle(shaftAngle * pole_pairs);
132136
}
133137
/*
134-
Update motor angles and set thr Uq voltage
138+
Iterative function looping FOC algorithm, setting Uq on the Motor
139+
The faster it can be run the better
135140
*/
136141
void BLDCMotor::loopFOC() {
137142
// voltage open loop loop
@@ -140,7 +145,10 @@ void BLDCMotor::loopFOC() {
140145
}
141146

142147
/*
143-
Update motor angles and velocities
148+
Iterative funciton running outer loop of the FOC algorithm
149+
Bahvior of this funciton is determined by the motor.controller variable
150+
It runs either angle, veloctiy, velocity ultra slow or voltage loop
151+
- needs to be called iteratively it is asynchronious function
144152
*/
145153
void BLDCMotor::move(float target) {
146154
// get angular velocity
@@ -176,6 +184,7 @@ void BLDCMotor::move(float target) {
176184
*/
177185
/*
178186
Method using FOC to set Uq to the motor at the optimal angle
187+
- for unipolar drivers - only positive values
179188
*/
180189
void BLDCMotor::setPhaseVoltageUnipolar(double Uq, double angle_el) {
181190

@@ -212,12 +221,14 @@ void BLDCMotor::setPhaseVoltageUnipolar(double Uq, double angle_el) {
212221
}
213222
/*
214223
Method using FOC to set Uq to the motor at the optimal angle
224+
- for bipolar drivers - posiitve and negative voltages
215225
*/
216226
void BLDCMotor::setPhaseVoltageBipolar(double Uq, double angle_el) {
217227

228+
// q component angle
229+
float angle = angle_el + M_PI/2;
218230
// Uq sign compensation
219-
float angle;// = angle + shaft_velocity*0.0003;
220-
angle = Uq > 0 ? angle_el : normalizeAngle( angle_el + M_PI );
231+
angle = Uq > 0 ? angle : normalizeAngle( angle + M_PI );
221232

222233
// Park transform
223234
Ualpha = abs(Uq) * cos(angle);
@@ -239,7 +250,7 @@ void BLDCMotor::setPhaseVoltageBipolar(double Uq, double angle_el) {
239250
Method using FOC to set Uq to the motor at the optimal angle
240251
*/
241252
void BLDCMotor::setPhaseVoltage(double Uq, double angle_el) {
242-
switch (driver_type) {
253+
switch (driver) {
243254
case DriverType::bipolar :
244255
// L6234
245256
setPhaseVoltageBipolar(Uq, angle_el);
@@ -251,13 +262,15 @@ void BLDCMotor::setPhaseVoltage(double Uq, double angle_el) {
251262
}
252263
}
253264

265+
254266
/*
255267
Set voltage to the pwm pin
256268
*/
257269
void BLDCMotor::setPwm(int pinPwm, float U) {
258270
int U_pwm = 0;
271+
int U_max = power_supply_voltage;
259272
// uniploar or bipolar FOC
260-
switch (driver_type) {
273+
switch (driver) {
261274
case DriverType::bipolar :
262275
// sets the voltage [-U_max,U_max] to pwm [0,255]
263276
// - U_max you can set in header file - default 12V
@@ -291,38 +304,25 @@ double BLDCMotor::normalizeAngle(double angle)
291304
double a = fmod(angle, 2 * M_PI);
292305
return a >= 0 ? a : (a + 2 * M_PI);
293306
}
294-
/*
295-
Reference low pass filter
296-
used to filter set point signal - to remove sharp changes
297-
*/
298-
float BLDCMotor::filterLP(float u) {
299-
static float Ts, yk_1;
300-
float M_Tau = 0.01;
301-
Ts = (micros() - Ts) * 1e-6;
302-
float y_k = Ts / (M_Tau + Ts) * u + (1 - Ts / (M_Tau + Ts)) * yk_1;
303-
Ts = micros();
304-
yk_1 = y_k;
305-
return y_k;
306-
}
307307

308308

309309

310310

311311
/**
312-
Motor `ntrol functions
312+
Motor control functions
313313
*/
314314
float BLDCMotor::velocityPI(float ek) {
315315
float Ts = (micros() - PI_velocity.timestamp) * 1e-6;
316316

317317
// u(s) = Kr(1 + 1/(Ti.s))
318318
float uk = PI_velocity.uk_1;
319319
uk += PI_velocity.K * (Ts / (2 * PI_velocity.Ti) + 1) * ek + PI_velocity.K * (Ts / (2 * PI_velocity.Ti) - 1) * PI_velocity.ek_1;
320-
if (abs(uk) > U_max) uk = uk > 0 ? U_max : -U_max;
320+
if (abs(uk) > PI_velocity.u_limit) uk = uk > 0 ? PI_velocity.u_limit : -PI_velocity.u_limit;
321321

322322
PI_velocity.uk_1 = uk;
323323
PI_velocity.ek_1 = ek;
324324
PI_velocity.timestamp = micros();
325-
return -uk;
325+
return uk;
326326
}
327327

328328
// PI controller for ultra slow velocity control
@@ -336,53 +336,20 @@ float BLDCMotor::velocityUltraSlowPI(float vel) {
336336
// u(s) = Kr(1 + 1/(Ti.s))
337337
float uk = PI_velocity_ultra_slow.uk_1;
338338
uk += PI_velocity_ultra_slow.K * (Ts / (2 * PI_velocity_ultra_slow.Ti) + 1) * ek + PI_velocity_ultra_slow.K * (Ts / (2 * PI_velocity_ultra_slow.Ti) - 1) * PI_velocity_ultra_slow.ek_1;
339-
if (abs(uk) > U_max) uk = uk > 0 ? U_max : -U_max;
339+
if (abs(uk) > PI_velocity_ultra_slow.u_limit) uk = uk > 0 ? PI_velocity_ultra_slow.u_limit : -PI_velocity_ultra_slow.u_limit;
340340

341341
PI_velocity_ultra_slow.uk_1 = uk;
342342
PI_velocity_ultra_slow.ek_1 = ek;
343343
PI_velocity_ultra_slow.timestamp = micros();
344-
return -uk;
344+
return uk;
345345
}
346346
// P controller for position control loop
347347
float BLDCMotor::positionP(float ek) {
348348
float velk = P_angle.K * ek;
349-
if (abs(velk) > velocity_max) velk = velk > 0 ? velocity_max : -velocity_max;
349+
if (abs(velk) > P_angle.velocity_limit) velk = velk > 0 ? P_angle.velocity_limit : -P_angle.velocity_limit;
350350
return velk;
351351
}
352352

353-
// voltage control loop api
354-
void BLDCMotor::setVoltage(float Uq) {
355-
voltage_q = Uq;
356-
}
357-
// shaft velocity loop api
358-
void BLDCMotor::setVelocity(float vel) {
359-
shaft_velocity_sp = vel;
360-
}
361-
362-
// utra slow shaft velocity loop api
363-
void BLDCMotor::setVelocityUltraSlow(float vel) {
364-
shaft_velocity_sp = vel;
365-
366-
shaft_velocity = shaftVelocity();
367-
static long timestamp;
368-
static float angle_1;
369-
if (!timestamp) {
370-
// init
371-
timestamp = micros();
372-
angle_1 = shaft_angle;
373-
}
374-
float dt = (micros() - timestamp) / 1e6;
375-
angle_1 += vel * dt;
376-
voltage_q = velocityUltraSlowPI(angle_1 - shaft_angle);
377-
timestamp = micros();
378-
}
379-
380-
// postion control loop
381-
void BLDCMotor::setPosition(float pos) {
382-
shaft_angle_sp = pos;
383-
}
384-
385-
386353

387354
/*
388355
High PWM frequency

0 commit comments

Comments
 (0)