Skip to content

Commit 5a03bab

Browse files
committed
FEAT space vector fixed, initFOC update, natural dir impl, restructured examples
1 parent fdaf9e2 commit 5a03bab

File tree

7 files changed

+61
-29
lines changed

7 files changed

+61
-29
lines changed

keywords.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ ControlType KEYWORD1
2929
FOCModulationType KEYWORD2
3030
Quadrature KEYWORD1
3131
Pullup KEYWORD1
32+
Direction KEYWORD1
3233

3334
linkSensor KEYWORD2
3435
handleA KEYWORD2
@@ -64,6 +65,13 @@ velocity KEYWORD2
6465
velocity_ultra_slow KEYWORD2
6566
angle KEYWORD2
6667

68+
69+
ON KEYWORD2
70+
OFF KEYWORD2
71+
CW KEYWORD2
72+
CCW KEYWORD2
73+
UNKNOWN KEYWORD2
74+
6775
P KEYWORD2
6876
I KEYWORD2
6977
Tf KEYWORD2

library.properties

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name=Simple FOC
22
version=1.4.2
3-
author=Antun Skuric <antun.skuric@outlook.com>
4-
maintainer=Antun Skuric <antun.skuric@outlook.com>
3+
author=Antun Skuric <info@simplefoc.com>
4+
maintainer=Antun Skuric <info@simplefoc.com>
55
sentence=A library demistifying FOC for BLDC motors
6-
paragraph=Simple library intended for hobby comunity to run the BLDC motor using FOC algorithm. It is interded both for plug&play and simple enough to be easy to extend. Library supports Arudino devices such as Arduino UNO, MEGA and similar, but also stm32 boards Nucleo and Bluepill.
6+
paragraph=Simple library intended for hobby comunity to run the BLDC motor using FOC algorithm. It is intended to support as many BLDC motor+sensor+driver combinations as possible and in the same time maintain simplicity of usage. Library supports Arudino devices such as Arduino UNO, MEGA, NANO and similar, stm32 boards Nucleo and Bluepill and ESP32 boards.
77
category=Device Control
88
url=https://docs.simplefoc.com
99
architectures=*

src/BLDCMotor.cpp

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,13 @@ int BLDCMotor::alignSensor() {
131131
} else if (mid_angle == start_angle) {
132132
if(monitor_port) monitor_port->println("MOT: Sensor failed to notice movement");
133133
}
134-
_delay(500);
135-
136-
// let the motor stabilize for 1 sec
137-
_delay(500);
134+
135+
// let the motor stabilize for 2 sec
136+
_delay(2000);
138137
// set sensor to zero
139138
sensor->initRelativeZero();
140139
_delay(500);
141-
setPhaseVoltage(0,angle);
140+
setPhaseVoltage(0,0);
142141
_delay(200);
143142

144143
// find the index if available
@@ -177,7 +176,7 @@ int BLDCMotor::absoluteZeroAlign() {
177176
// align the sensor with the absolute zero
178177
float zero_offset = sensor->initAbsoluteZero();
179178
// remember zero electric angle
180-
zero_electric_angle = electricAngle(zero_offset);
179+
zero_electric_angle = normalizeAngle(electricAngle(zero_offset));
181180
}
182181
// return bool if zero found
183182
return !sensor->needsAbsoluteZeroSearch() ? 1 : -1;
@@ -213,12 +212,21 @@ float BLDCMotor::electricAngle(float shaftAngle) {
213212
FOC functions
214213
*/
215214
// FOC initialization function
216-
int BLDCMotor::initFOC() {
217-
// sensor and motor alignment
218-
_delay(500);
219-
int exit_flag = alignSensor();
220-
_delay(500);
221-
215+
int BLDCMotor::initFOC( float zero_electric_offset, Direction sensor_direction) {
216+
int exit_flag = 1;
217+
// align motor if necessary
218+
// alignment necessary for encoders!
219+
if(zero_electric_offset != NOT_SET){
220+
// abosolute zero offset provided - no need to align
221+
zero_electric_angle = zero_electric_offset;
222+
// set the sensor direction - default CW
223+
sensor->natural_direction = sensor_direction;
224+
}else{
225+
// sensor and motor alignment
226+
_delay(500);
227+
exit_flag = alignSensor();
228+
_delay(500);
229+
}
222230
if(monitor_port) monitor_port->println("MOT: Motor ready.");
223231

224232
return exit_flag;
@@ -307,13 +315,13 @@ void BLDCMotor::setPhaseVoltage(float Uq, float angle_el) {
307315
// find the sector we are in currently
308316
int sector = floor(angle_el / _PI_3) + 1;
309317
// calculate the duty cycles
310-
float T1 = _SQRT3*_sin(sector*_PI_3 - angle_el);
311-
float T2 = _SQRT3*_sin(angle_el - (sector-1.0)*_PI_3);
318+
float T1 = _SQRT3*_sin(sector*_PI_3 - angle_el) * Uq/voltage_power_supply;
319+
float T2 = _SQRT3*_sin(angle_el - (sector-1.0)*_PI_3) * Uq/voltage_power_supply;
312320
// two versions possible
313321
// centered around voltage_power_supply/2
314322
float T0 = 1 - T1 - T2;
315323
// pulled to 0 - better for low power supply voltage
316-
//T0 = 0;
324+
//float T0 = 0;
317325

318326
// calculate the duty cycles(times)
319327
float Ta,Tb,Tc;
@@ -356,9 +364,9 @@ void BLDCMotor::setPhaseVoltage(float Uq, float angle_el) {
356364
}
357365

358366
// calculate the phase voltages and center
359-
Ua = Ta*Uq + (voltage_power_supply - Uq) / 2;
360-
Ub = Tb*Uq + (voltage_power_supply - Uq) / 2;
361-
Uc = Tc*Uq + (voltage_power_supply - Uq) / 2;
367+
Ua = Ta*voltage_power_supply;// + (voltage_power_supply - Uq) / 2;
368+
Ub = Tb*voltage_power_supply;// + (voltage_power_supply - Uq) / 2;
369+
Uc = Tc*voltage_power_supply;// + (voltage_power_supply - Uq) / 2;
362370
break;
363371
}
364372

src/BLDCMotor.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,14 @@ class BLDCMotor
9797
/**
9898
* Function initializing FOC algorithm
9999
* and aligning sensor's and motors' zero position
100+
*
101+
* - If zero_electric_offset parameter is set the alignment procedure is skipped
102+
*
103+
* @param zero_electric_offset value of the sensors absolute position electrical offset in respect to motor's electrical 0 position.
104+
* @param sensor_direction sensor natural direction - default is CW
105+
*
100106
*/
101-
int initFOC();
107+
int initFOC( float zero_electric_offset = NOT_SET , Direction sensor_direction = Direction::CW);
102108
/**
103109
* Function running FOC algorithm in real-time
104110
* it calculates the gets motor angle and sets the appropriate voltages

src/Encoder.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ void Encoder::handleIndex() {
107107
Shaft angle calculation
108108
*/
109109
float Encoder::getAngle(){
110-
return _2PI * (pulse_counter) / ((float)cpr);
110+
return natural_direction * _2PI * (pulse_counter) / ((float)cpr);
111111
}
112112
/*
113113
Shaft velocity calculation
@@ -145,7 +145,7 @@ float Encoder::getVelocity(){
145145
// save velocity calculation variables
146146
prev_Th = Th;
147147
prev_pulse_counter = pulse_counter;
148-
return (velocity);
148+
return natural_direction * (velocity);
149149
}
150150

151151
// getter for index pin

src/MagneticSensorI2C.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ MagneticSensorI2C::MagneticSensorI2C(uint8_t _chip_address, int _bit_resolution,
1111
// angle read register of the magnetic sensor
1212
angle_register_msb = _angle_register_msb;
1313
// register maximum value (counts per revolution)
14-
cpr = pow(2,_bit_resolution);
14+
cpr = pow(2, _bit_resolution);
1515

1616
// depending on the sensor architecture there are different combinations of
1717
// LSB and MSB register used bits
@@ -60,7 +60,7 @@ float MagneticSensorI2C::getAngle(){
6060
angle_data -= (int)zero_offset;
6161
// return the full angle
6262
// (number of full rotations)*2PI + current sensor angle
63-
return full_rotation_offset + ( angle_data / (float)cpr) * _2PI;
63+
return natural_direction * (full_rotation_offset + ( angle_data / (float)cpr) * _2PI);
6464
}
6565

6666
// Shaft velocity calculation
@@ -85,7 +85,7 @@ float MagneticSensorI2C::getVelocity(){
8585
// return the angle [rad] difference
8686
float MagneticSensorI2C::initRelativeZero(){
8787
float angle_offset = -getAngle();
88-
zero_offset = getRawCount();
88+
zero_offset = natural_direction * getRawCount();
8989

9090
// angle tracking variables
9191
full_rotation_offset = 0;

src/MagneticSensorSPI.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ void MagneticSensorSPI::init(){
2525

2626
//SPI has an internal SPI-device counter, it is possible to call "begin()" from different devices
2727
SPI.begin();
28+
#ifndef ESP_H // if not ESP32 board
2829
SPI.setBitOrder(MSBFIRST); // Set the SPI_1 bit order
2930
SPI.setDataMode(SPI_MODE1) ;
3031
SPI.setClockDivider(SPI_CLOCK_DIV8);
32+
#endif
3133

3234
digitalWrite(chip_select_pin, HIGH);
3335
// velocity calculation init
@@ -60,7 +62,7 @@ float MagneticSensorSPI::getAngle(){
6062
angle_data -= (int)zero_offset;
6163
// return the full angle
6264
// (number of full rotations)*2PI + current sensor angle
63-
return full_rotation_offset + ( angle_data / (float)cpr) * _2PI;
65+
return natural_direction * (full_rotation_offset + ( angle_data / (float)cpr) * _2PI);
6466
}
6567

6668
// Shaft velocity calculation
@@ -85,7 +87,7 @@ float MagneticSensorSPI::getVelocity(){
8587
// return the angle [rad] difference
8688
float MagneticSensorSPI::initRelativeZero(){
8789
float angle_offset = -getAngle();
88-
zero_offset = getRawCount();
90+
zero_offset = natural_direction * getRawCount();
8991

9092
// angle tracking variables
9193
full_rotation_offset = 0;
@@ -164,13 +166,21 @@ word MagneticSensorSPI::read(word angle_register){
164166

165167
//Send the command
166168
digitalWrite(chip_select_pin, LOW);
169+
#ifndef ESP_H // if not ESP32 board
167170
digitalWrite(chip_select_pin, LOW);
171+
#endif
168172
SPI.transfer(left_byte);
169173
SPI.transfer(right_byte);
170174
digitalWrite(chip_select_pin,HIGH);
175+
#ifndef ESP_H // if not ESP32 board
171176
digitalWrite(chip_select_pin,HIGH);
177+
#endif
172178

179+
#if defined( ESP_H ) // if ESP32 board
180+
delayMicroseconds(50);
181+
#else
173182
delayMicroseconds(10);
183+
#endif
174184

175185
//Now read the response
176186
digitalWrite(chip_select_pin, LOW);

0 commit comments

Comments
 (0)