Skip to content

Commit 50a758b

Browse files
check for floating point error due to insufficient precision
1 parent ea128de commit 50a758b

File tree

1 file changed

+30
-24
lines changed

1 file changed

+30
-24
lines changed

src/BLDCMotor.cpp

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ void BLDCMotor::linkDriver(BLDCDriver* _driver) {
2929
driver = _driver;
3030
}
3131

32-
// init hardware pins
32+
// init hardware pins
3333
void BLDCMotor::init() {
3434
if(monitor_port) monitor_port->println("MOT: Initialise variables.");
3535
// sanity check for the voltage limit configuration
@@ -53,13 +53,13 @@ void BLDCMotor::disable()
5353
{
5454
// set zero to PWM
5555
driver->setPwm(0, 0, 0);
56-
// disable the driver
56+
// disable the driver
5757
driver->disable();
5858
}
5959
// enable motor driver
6060
void BLDCMotor::enable()
6161
{
62-
// enable the driver
62+
// enable the driver
6363
driver->enable();
6464
// set zero to PWM
6565
driver->setPwm(0, 0, 0);
@@ -93,7 +93,7 @@ int BLDCMotor::initFOC( float zero_electric_offset, Direction sensor_direction
9393
int BLDCMotor::alignSensor() {
9494
if(monitor_port) monitor_port->println("MOT: Align sensor.");
9595
// align the electrical phases of the motor and sensor
96-
// set angle -90 degrees
96+
// set angle -90 degrees
9797

9898
float start_angle = shaftAngle();
9999
for (int i = 0; i <=5; i++ ) {
@@ -134,19 +134,19 @@ int BLDCMotor::alignSensor() {
134134
}
135135

136136

137-
// Encoder alignment the absolute zero angle
137+
// Encoder alignment the absolute zero angle
138138
// - to the index
139139
int BLDCMotor::absoluteZeroAlign() {
140140

141141
if(monitor_port) monitor_port->println("MOT: Absolute zero align.");
142142
// if no absolute zero return
143143
if(!sensor->hasAbsoluteZero()) return 0;
144-
144+
145145

146146
if(monitor_port && sensor->needsAbsoluteZeroSearch()) monitor_port->println("MOT: Searching...");
147147
// search the absolute zero with small velocity
148148
while(sensor->needsAbsoluteZeroSearch() && shaft_angle < _2PI){
149-
loopFOC();
149+
loopFOC();
150150
voltage_q = PID_velocity(velocity_index_search - shaftVelocity());
151151
}
152152
voltage_q = 0;
@@ -167,9 +167,9 @@ int BLDCMotor::absoluteZeroAlign() {
167167
// Iterative function looping FOC algorithm, setting Uq on the Motor
168168
// The faster it can be run the better
169169
void BLDCMotor::loopFOC() {
170-
// shaft angle
170+
// shaft angle
171171
shaft_angle = shaftAngle();
172-
// set the phase voltage - FOC heart function :)
172+
// set the phase voltage - FOC heart function :)
173173
setPhaseVoltage(voltage_q, voltage_d, _electricalAngle(shaft_angle,pole_pairs));
174174
}
175175

@@ -219,7 +219,7 @@ void BLDCMotor::move(float new_target) {
219219

220220
// Method using FOC to set Uq and Ud to the motor at the optimal angle
221221
// Function implementing Space Vector PWM and Sine PWM algorithms
222-
//
222+
//
223223
// Function using sine approximation
224224
// regular sin + cos ~300us (no memory usaage)
225225
// approx _sin + _cos ~110us (400Byte ~ 20% of memory)
@@ -257,7 +257,7 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
257257
};
258258
// static int trap_150_state = 0;
259259
sector = 12 * (_normalizeAngle(angle_el + PI/6.0 + zero_electric_angle) / _2PI); // adding PI/6 to align with other modes
260-
260+
261261
Ua = Uq + trap_150_map[sector][0] * Uq;
262262
Ub = Uq + trap_150_map[sector][1] * Uq;
263263
Uc = Uq + trap_150_map[sector][2] * Uq;
@@ -272,7 +272,7 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
272272
break;
273273

274274
case FOCModulationType::SinePWM :
275-
// Sinusoidal PWM modulation
275+
// Sinusoidal PWM modulation
276276
// Inverse Park + Clarke transformation
277277

278278
// angle normalization in between 0 and 2pi
@@ -299,10 +299,10 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
299299
break;
300300

301301
case FOCModulationType::SpaceVectorPWM :
302-
// Nice video explaining the SpaceVectorModulation (SVPWM) algorithm
302+
// Nice video explaining the SpaceVectorModulation (SVPWM) algorithm
303303
// https://www.youtube.com/watch?v=QMSWUMEAejg
304304

305-
// if negative voltages change inverse the phase
305+
// if negative voltages change inverse the phase
306306
// angle + 180degrees
307307
if(Uq < 0) angle_el += _PI;
308308
Uq = abs(Uq);
@@ -316,14 +316,14 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
316316
// calculate the duty cycles
317317
float T1 = _SQRT3*_sin(sector*_PI_3 - angle_el) * Uq/driver->voltage_limit;
318318
float T2 = _SQRT3*_sin(angle_el - (sector-1.0)*_PI_3) * Uq/driver->voltage_limit;
319-
// two versions possible
319+
// two versions possible
320320
float T0 = 0; // pulled to 0 - better for low power supply voltage
321-
if (centered) {
321+
if (centered) {
322322
T0 = 1 - T1 - T2; //centered around driver->voltage_limit/2
323-
}
323+
}
324324

325325
// calculate the duty cycles(times)
326-
float Ta,Tb,Tc;
326+
float Ta,Tb,Tc;
327327
switch(sector){
328328
case 1:
329329
Ta = T1 + T2 + T0/2;
@@ -369,7 +369,7 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
369369
break;
370370

371371
}
372-
372+
373373
// set the voltages in driver
374374
driver->setPwm(Ua, Ub, Uc);
375375
}
@@ -386,7 +386,13 @@ void BLDCMotor::velocityOpenloop(float target_velocity){
386386
float Ts = (now_us - open_loop_timestamp) * 1e-6;
387387

388388
// calculate the necessary angle to achieve target velocity
389-
shaft_angle += target_velocity*Ts;
389+
shaft_angle += target_velocity*Ts;
390+
391+
// check if shaft_angle gets too large
392+
if (shaft_angle >= (_2PI * 4))
393+
{
394+
shaft_angle = 0;
395+
}
390396

391397
// set the maximal allowed voltage (voltage_limit) with the necessary angle
392398
setPhaseVoltage(voltage_limit, 0, _electricalAngle(shaft_angle, pole_pairs));
@@ -403,17 +409,17 @@ void BLDCMotor::angleOpenloop(float target_angle){
403409
unsigned long now_us = _micros();
404410
// calculate the sample time from last call
405411
float Ts = (now_us - open_loop_timestamp) * 1e-6;
406-
412+
407413
// calculate the necessary angle to move from current position towards target angle
408414
// with maximal velocity (velocity_limit)
409415
if(abs( target_angle - shaft_angle ) > abs(velocity_limit*Ts))
410-
shaft_angle += _sign(target_angle - shaft_angle) * abs( velocity_limit )*Ts;
416+
shaft_angle += _sign(target_angle - shaft_angle) * abs( velocity_limit )*Ts;
411417
else
412418
shaft_angle = target_angle;
413-
419+
414420
// set the maximal allowed voltage (voltage_limit) with the necessary angle
415421
setPhaseVoltage(voltage_limit, 0, _electricalAngle(shaft_angle, pole_pairs));
416422

417423
// save timestamp for next call
418424
open_loop_timestamp = now_us;
419-
}
425+
}

0 commit comments

Comments
 (0)