SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
CurrentSense.cpp
Go to the documentation of this file.
1#include "CurrentSense.h"
2#include "../../communication/SimpleFOCDebug.h"
3
4
5// get current magnitude
6// - absolute - if no electrical_angle provided
7// - signed - if angle provided
8float CurrentSense::getDCCurrent(float motor_electrical_angle){
9 // read current phase currents
11
12 // calculate clarke transform
13 ABCurrent_s ABcurrent = getABCurrents(current);
14
15 // current sign - if motor angle not provided the magnitude is always positive
16 float sign = 1;
17
18 // if motor angle provided function returns signed value of the current
19 // determine the sign of the current
20 // sign(atan2(current.q, current.d)) is the same as c.q > 0 ? 1 : -1
21 if(motor_electrical_angle) {
22 float ct;
23 float st;
24 _sincos(motor_electrical_angle, &st, &ct);
25 sign = (ABcurrent.beta*ct - ABcurrent.alpha*st) > 0 ? 1 : -1;
26 }
27 // return current magnitude
28 return sign*_sqrt(ABcurrent.alpha*ABcurrent.alpha + ABcurrent.beta*ABcurrent.beta);
29}
30
31// function used with the foc algorithm
32// calculating DQ currents from phase currents
33// - function calculating park and clarke transform of the phase currents
34// - using getPhaseCurrents and getABCurrents internally
36 // read current phase currents
38
39 // calculate clarke transform
40 ABCurrent_s ABcurrent = getABCurrents(current);
41
42 // calculate park transform
43 DQCurrent_s return_current = getDQCurrents(ABcurrent,angle_el);
44
45 return return_current;
46}
47
48// function used with the foc algorithm
49// calculating Alpha Beta currents from phase currents
50// - function calculating Clarke transform of the phase currents
52
53 // check if driver is an instance of StepperDriver
54 // if so there is no need to Clarke transform
56 ABCurrent_s return_ABcurrent;
57 return_ABcurrent.alpha = current.a;
58 return_ABcurrent.beta = current.b;
59 return return_ABcurrent;
60 }
61
63 ABCurrent_s return_ABcurrent;
64 //ia + ib + ic = 0
65 if(current.a == 0){
66 return_ABcurrent.alpha = -current.c - current.b;
67 return_ABcurrent.beta = current.b;
68 }else if(current.b == 0){
69 return_ABcurrent.alpha = current.a;
70 return_ABcurrent.beta = -current.c - current.a;
71 }else{
72 return_ABcurrent.alpha = current.a;
73 return_ABcurrent.beta = current.b;
74 }
75 return return_ABcurrent;
76 }
77
78 // otherwise it's a BLDC motor and
79 // calculate clarke transform
80 float i_alpha, i_beta;
81 if(!current.c){
82 // if only two measured currents
83 i_alpha = current.a;
84 i_beta = _1_SQRT3 * current.a + _2_SQRT3 * current.b;
85 }else if(!current.a){
86 // if only two measured currents
87 float a = -current.c - current.b;
88 i_alpha = a;
89 i_beta = _1_SQRT3 * a + _2_SQRT3 * current.b;
90 }else if(!current.b){
91 // if only two measured currents
92 float b = -current.a - current.c;
93 i_alpha = current.a;
94 i_beta = _1_SQRT3 * current.a + _2_SQRT3 * b;
95 } else {
96 // signal filtering using identity a + b + c = 0. Assumes measurement error is normally distributed.
97 float mid = (1.f/3) * (current.a + current.b + current.c);
98 float a = current.a - mid;
99 float b = current.b - mid;
100 i_alpha = a;
101 i_beta = _1_SQRT3 * a + _2_SQRT3 * b;
102 }
103
104 ABCurrent_s return_ABcurrent;
105 return_ABcurrent.alpha = i_alpha;
106 return_ABcurrent.beta = i_beta;
107 return return_ABcurrent;
108}
109
110// function used with the foc algorithm
111// calculating D and Q currents from Alpha Beta currents and electrical angle
112// - function calculating Clarke transform of the phase currents
114 // calculate park transform
115 float ct;
116 float st;
117 _sincos(angle_el, &st, &ct);
118 DQCurrent_s return_current;
119 return_current.d = current.alpha * ct + current.beta * st;
120 return_current.q = current.beta * ct - current.alpha * st;
121 return return_current;
122}
123
124/**
125 Driver linking to the current sense
126*/
128 driver = _driver;
129 // save the driver type for easier access
131}
132
133
135 // nothing is done here, but you can override this function
136};
137
139 // nothing is done here, but you can override this function
140};
141
142
143// Function aligning the current sense with motor driver
144// if all pins are connected well none of this is really necessary! - can be avoided
145// returns flag
146// 0 - fail
147// 1 - success and nothing changed
148// 2 - success but pins reconfigured
149// 3 - success but gains inverted
150// 4 - success but pins reconfigured and gains inverted
151// IMPORTANT, this function can be overriden in the child class
152int CurrentSense::driverAlign(float voltage, bool modulation_centered){
153
154 int exit_flag = 1;
155 if(skip_align) return exit_flag;
156
157 if (!initialized) return 0;
158
159 // check if stepper or BLDC
160 switch(driver_type){
161 case DriverType::BLDC:
162 return alignBLDCDriver(voltage, (BLDCDriver*)driver, modulation_centered);
164 return alignStepperDriver(voltage, (StepperDriver*)driver, modulation_centered);
166 return alignHybridDriver(voltage, (BLDCDriver*)driver, modulation_centered);
167 default:
168 // driver type not supported
169 SIMPLEFOC_DEBUG("CS: Cannot align driver type!");
170 return 0;
171 }
172}
173
174
175
176// Helper function to read and average phase currents
179 for (int i = 0; i < N; i++) {
181 c.a = c.a * 0.6f + 0.4f * c1.a;
182 c.b = c.b * 0.6f + 0.4f * c1.b;
183 c.c = c.c * 0.6f + 0.4f * c1.c;
184 _delay(3);
185 }
186 return c;
187};
188
189
190
191// Function aligning the current sense with motor driver
192// if all pins are connected well none of this is really necessary! - can be avoided
193// returns flag
194// 0 - fail
195// 1 - success and nothing changed
196// 2 - success but pins reconfigured
197// 3 - success but gains inverted
198// 4 - success but pins reconfigured and gains inverted
199int CurrentSense::alignBLDCDriver(float voltage, BLDCDriver* bldc_driver, bool modulation_centered){
200
201 bool phases_switched = 0;
202 bool phases_inverted = 0;
203
204 float zero = 0;
205 if(modulation_centered) zero = driver->voltage_limit/2.0;
206
207 // set phase A active and phases B and C down
208 // 300 ms of ramping
209 for(int i=0; i < 100; i++){
210 bldc_driver->setPwm(voltage/100.0*((float)i)+zero , zero, zero);
211 _delay(3);
212 }
213 _delay(500);
215 bldc_driver->setPwm(zero, zero, zero);
216 // check if currents are to low (lower than 100mA)
217 // TODO calculate the 100mA threshold from the ADC resolution
218 // if yes throw an error and return 0
219 // either the current sense is not connected or the current is
220 // too low for calibration purposes (one should raise the motor.voltage_sensor_align)
221 if((fabs(c_a.a) < 0.1f) && (fabs(c_a.b) < 0.1f) && (fabs(c_a.c) < 0.1f)){
222 SIMPLEFOC_DEBUG("CS: Err too low current, rise voltage!");
223 return 0; // measurement current too low
224 }
225
226
227 // now we have to determine
228 // 1) which pin correspond to which phase of the bldc driver
229 // 2) if the currents measured have good polarity
230 //
231 // > when we apply a voltage to a phase A of the driver what we expect to measure is the current I on the phase A
232 // and -I/2 on the phase B and I/2 on the phase C
233
234 // find the highest magnitude in c_a
235 // and make sure it's around 2 (1.5 at least) times higher than the other two
236 float ca[3] = {fabs(c_a.a), fabs(c_a.b), fabs(c_a.c)};
237 uint8_t max_i = -1; // max index
238 float max_c = 0; // max current
239 float max_c_ratio = 0; // max current ratio
240 for(int i = 0; i < 3; i++){
241 if(!ca[i]) continue; // current not measured
242 if(ca[i] > max_c){
243 max_c = ca[i];
244 max_i = i;
245 for(int j = 0; j < 3; j++){
246 if(i == j) continue;
247 if(!ca[j]) continue; // current not measured
248 float ratio = max_c / ca[j];
249 if(ratio > max_c_ratio) max_c_ratio = ratio;
250 }
251 }
252 }
253
254 // check the current magnitude ratios
255 // 1) if there is one current that is approximately 2 times higher than the other two
256 // this is the A current
257 // 2) if the max current is not at least 1.5 times higher than the other two
258 // we have two cases:
259 // - either we only measure two currents and the third one is not measured - then phase A is not measured
260 // - or the current sense is not connected properly
261
262 if(max_c_ratio >=1.5f){
263 switch (max_i){
264 case 1: // phase B is the max current
265 SIMPLEFOC_DEBUG("CS: Switch A-B");
266 // switch phase A and B
267 _swap(pinA, pinB);
270 _swap(c_a.b, c_a.b);
271 phases_switched = true; // signal that pins have been switched
272 break;
273 case 2: // phase C is the max current
274 SIMPLEFOC_DEBUG("CS: Switch A-C");
275 // switch phase A and C
276 _swap(pinA, pinC);
279 _swap(c_a.a, c_a.c);
280 phases_switched = true;// signal that pins have been switched
281 break;
282 }
283 // check if the current is negative and invert the gain if so
284 if( _sign(c_a.a) < 0 ){
285 SIMPLEFOC_DEBUG("CS: Inv A");
286 gain_a *= -1;
287 phases_inverted = true; // signal that pins have been inverted
288 }
289 }else if(_isset(pinA) && _isset(pinB) && _isset(pinC)){
290 // if all three currents are measured and none of them is significantly higher
291 // we have a problem with the current sense
292 SIMPLEFOC_DEBUG("CS: Err A - all currents same magnitude!");
293 return 0;
294 }else{ //phase A is not measured so put the _NC to the phase A
295 if(_isset(pinA) && !_isset(pinB)){
296 SIMPLEFOC_DEBUG("CS: Switch A-(B)NC");
297 _swap(pinA, pinB);
300 _swap(c_a.b, c_a.b);
301 phases_switched = true; // signal that pins have been switched
302 }else if(_isset(pinA) && !_isset(pinC)){
303 SIMPLEFOC_DEBUG("CS: Switch A-(C)NC");
304 _swap(pinA, pinC);
307 _swap(c_a.b, c_a.c);
308 phases_switched = true; // signal that pins have been switched
309 }
310 }
311 // at this point the current sensing on phase A can be either:
312 // - aligned with the driver phase A
313 // - or the phase A is not measured and the _NC is connected to the phase A
314 //
315 // In either case A is done, now we have to check the phase B and C
316
317
318 // set phase B active and phases A and C down
319 // 300 ms of ramping
320 for(int i=0; i < 100; i++){
321 bldc_driver->setPwm(zero, voltage/100.0*((float)i)+zero, zero);
322 _delay(3);
323 }
324 _delay(500);
326 bldc_driver->setPwm(zero, zero, zero);
327
328 // check the phase B
329 // find the highest magnitude in c_b
330 // and make sure it's around 2 (1.5 at least) times higher than the other two
331 float cb[3] = {fabs(c_b.a), fabs(c_b.b), fabs(c_b.c)};
332 max_i = -1; // max index
333 max_c = 0; // max current
334 max_c_ratio = 0; // max current ratio
335 for(int i = 0; i < 3; i++){
336 if(!cb[i]) continue; // current not measured
337 if(cb[i] > max_c){
338 max_c = cb[i];
339 max_i = i;
340 for(int j = 0; j < 3; j++){
341 if(i == j) continue;
342 if(!cb[j]) continue; // current not measured
343 float ratio = max_c / cb[j];
344 if(ratio > max_c_ratio) max_c_ratio = ratio;
345 }
346 }
347 }
348 if(max_c_ratio >= 1.5f){
349 switch (max_i){
350 case 0: // phase A is the max current
351 // this is an error as phase A is already aligned
352 SIMPLEFOC_DEBUG("CS: Err align B");
353 return 0;
354 case 2: // phase C is the max current
355 SIMPLEFOC_DEBUG("CS: Switch B-C");
356 _swap(pinB, pinC);
359 _swap(c_b.b, c_b.c);
360 phases_switched = true; // signal that pins have been switched
361 break;
362 }
363 // check if the current is negative and invert the gain if so
364 if( _sign(c_b.b) < 0 ){
365 SIMPLEFOC_DEBUG("CS: Inv B");
366 gain_b *= -1;
367 phases_inverted = true; // signal that pins have been inverted
368 }
369 }else if(_isset(pinB) && _isset(pinC)){
370 // if all three currents are measured and none of them is significantly higher
371 // we have a problem with the current sense
372 SIMPLEFOC_DEBUG("CS: Err B - all currents same magnitude!");
373 return 0;
374 }else{ //phase B is not measured so put the _NC to the phase B
375 if(_isset(pinB) && !_isset(pinC)){
376 SIMPLEFOC_DEBUG("CS: Switch B-(C)NC");
377 _swap(pinB, pinC);
380 _swap(c_b.b, c_b.c);
381 phases_switched = true; // signal that pins have been switched
382 }
383 }
384 // at this point the current sensing on phase A and B can be either:
385 // - aligned with the driver phase A and B
386 // - or the phase A and B are not measured and the _NC is connected to the phase A and B
387 //
388 // In either case A and B is done, now we have to check the phase C
389 // phase C is also aligned if it is measured (not _NC)
390 // we have to check if the current is negative and invert the gain if so
391 if(_isset(pinC)){
392 if( _sign(c_b.c) > 0 ){ // the expected current is -I/2 (if the phase A and B are aligned and C has correct polarity)
393 SIMPLEFOC_DEBUG("CS: Inv C");
394 gain_c *= -1;
395 phases_inverted = true; // signal that pins have been inverted
396 }
397 }
398
399 // construct the return flag
400 // if the phases have been switched return 2
401 // if the gains have been inverted return 3
402 // if both return 4
403 uint8_t exit_flag = 1;
404 if(phases_switched) exit_flag += 1;
405 if(phases_inverted) exit_flag += 2;
406 return exit_flag;
407}
408
409
410// Function aligning the current sense with motor driver
411// if all pins are connected well none of this is really necessary! - can be avoided
412// returns flag
413// 0 - fail
414// 1 - success and nothing changed
415// 2 - success but pins reconfigured
416// 3 - success but gains inverted
417// 4 - success but pins reconfigured and gains inverted
418int CurrentSense::alignStepperDriver(float voltage, StepperDriver* stepper_driver, bool modulation_centered){
419
420 _UNUSED(modulation_centered);
421
422 bool phases_switched = 0;
423 bool phases_inverted = 0;
424
425 if(!_isset(pinA) || !_isset(pinB)){
426 SIMPLEFOC_DEBUG("CS: Pins A & B not specified!");
427 return 0;
428 }
429
430 // set phase A active and phases B down
431 // ramp 300ms
432 for(int i=0; i < 100; i++){
433 stepper_driver->setPwm(voltage/100.0*((float)i), 0);
434 _delay(3);
435 }
436 _delay(500);
438 // disable the phases
439 stepper_driver->setPwm(0, 0);
440 if (fabs(c.a) < 0.1f && fabs(c.b) < 0.1f ){
441 SIMPLEFOC_DEBUG("CS: Err too low current!");
442 return 0; // measurement current too low
443 }
444 // align phase A
445 // 1) only one phase can be measured so we first measure which ADC pin corresponds
446 // to the phase A by comparing the magnitude
447 if (fabs(c.a) < fabs(c.b)){
448 SIMPLEFOC_DEBUG("CS: Switch A-B");
449 // switch phase A and B
450 _swap(pinA, pinB);
453 phases_switched = true; // signal that pins have been switched
454 }
455 // 2) check if measured current a is positive and invert if not
456 if (c.a < 0){
457 SIMPLEFOC_DEBUG("CS: Inv A");
458 gain_a *= -1;
459 phases_inverted = true; // signal that pins have been inverted
460 }
461
462 // at this point the driver's phase A is aligned with the ADC pinA
463 // and the pin B should be the phase B
464
465 // set phase B active and phases A down
466 // ramp 300ms
467 for(int i=0; i < 100; i++){
468 stepper_driver->setPwm(0, voltage/100.0*((float)i));
469 _delay(3);
470 }
471 _delay(500);
473 stepper_driver->setPwm(0, 0);
474
475 // phase B should be aligned
476 // 1) we just need to verify that it has been measured
477 if (fabs(c.b) < 0.1f ){
478 SIMPLEFOC_DEBUG("CS: Err too low current on B!");
479 return 0; // measurement current too low
480 }
481 // 2) check if measured current a is positive and invert if not
482 if (c.b < 0){
483 SIMPLEFOC_DEBUG("CS: Inv B");
484 gain_b *= -1;
485 phases_inverted = true; // signal that pins have been inverted
486 }
487
488 // construct the return flag
489 // if success and nothing changed return 1
490 // if the phases have been switched return 2
491 // if the gains have been inverted return 3
492 // if both return 4
493 uint8_t exit_flag = 1;
494 if(phases_switched) exit_flag += 1;
495 if(phases_inverted) exit_flag += 2;
496 return exit_flag;
497}
498
499
500
501
502
503int CurrentSense::alignHybridDriver(float voltage, BLDCDriver* bldc_driver, bool modulation_centered){
504
505 _UNUSED(modulation_centered);
506
507 bool phases_switched = 0;
508 bool phases_inverted = 0;
509
510 // first find the middle phase, which will be set to the C phase
511 // set phase A active and phases B active, and C down
512 // ramp 300ms
513 for(int i=0; i < 100; i++){
514 bldc_driver->setPwm(voltage/100.0*((float)i), voltage/100.0*((float)i), 0);
515 _delay(3);
516 }
517 _delay(500);
519 // disable the phases
520 bldc_driver->setPwm(0, 0, 0);
521 if (fabs(c.a) < 0.1f && fabs(c.b) < 0.1f && fabs(c.c) < 0.1f ){
522 SIMPLEFOC_DEBUG("CS: Err too low current!");
523 return 0; // measurement current too low
524 }
525 // find the highest magnitude in c
526 // and make sure it's around 2 (1.5 at least) times higher than the other two
527 float cc[3] = {fabs(c.a), fabs(c.b), fabs(c.c)};
528 uint8_t max_i = -1; // max index
529 float max_c = 0; // max current
530 float max_c_ratio = 0; // max current ratio
531 for(int i = 0; i < 3; i++){
532 if(!cc[i]) continue; // current not measured
533 if(cc[i] > max_c){
534 max_c = cc[i];
535 max_i = i;
536 for(int j = 0; j < 3; j++){
537 if(i == j) continue;
538 if(!cc[j]) continue; // current not measured
539 float ratio = max_c / cc[j];
540 if(ratio > max_c_ratio) max_c_ratio = ratio;
541 }
542 }
543 }
544 if(max_c_ratio >=1.5f){
545 switch (max_i){
546 case 0: // phase A is the max current
547 SIMPLEFOC_DEBUG("CS: Switch A-C");
548 // switch phase A and C
549 _swap(pinA, pinC);
552 _swap(c.a, c.c);
553 phases_switched = true; // signal that pins have been switched
554 break;
555 case 1: // phase B is the max current
556 SIMPLEFOC_DEBUG("CS: Switch B-C");
557 // switch phase B and C
558 _swap(pinB, pinC);
561 _swap(c.b, c.c);
562 phases_switched = true; // signal that pins have been switched
563 break;
564 }
565 // check if the current is positive and invert the gain if so
566 // current c should be negative
567 if( _sign(c.c) > 0 ){
568 SIMPLEFOC_DEBUG("CS: Inv C");
569 gain_c *= -1;
570 phases_inverted = true; // signal that pins have been inverted
571 }
572 }else{
573 // c - middle phase is not measured
574 SIMPLEFOC_DEBUG("CS: Middle phase not measured!");
575 if(_isset(pinC)){
576 // switch the missing phase with the phase C
577 if(!_isset(pinA)){
578 SIMPLEFOC_DEBUG("CS: Switch (A)NC-C");
579 _swap(pinA, pinC);
582 _swap(c.a, c.c);
583 phases_switched = true; // signal that pins have been switched
584 }else if(!_isset(pinB)){
585 SIMPLEFOC_DEBUG("CS: Switch (B)NC-C");
586 _swap(pinB, pinC);
589 _swap(c.b, c.c);
590 phases_switched = true; // signal that pins have been switched
591 }
592 }
593 }
594
595 // at this point the current sensing on phase A and B can be either:
596 // - aligned with the driver phase A and B
597 // - or the phase A and B are not measured and the _NC is connected to the phase A and B
598
599 // Find the phase A
600
601 // set phase A active and phases B down
602 // ramp 300ms
603 for(int i=0; i < 100; i++){
604 bldc_driver->setPwm(voltage/100.0*((float)i), 0, 0);
605 _delay(3);
606 }
607 _delay(500);
609 // disable the phases
610 bldc_driver->setPwm(0, 0, 0);
611
612 // check if currents are to low (lower than 100mA)
613 if((fabs(c.a) < 0.1f) && (fabs(c.b) < 0.1f) && (fabs(c.c) < 0.1f)){
614 SIMPLEFOC_DEBUG("CS: Err too low current, rise voltage!");
615 return 0; // measurement current too low
616 }
617
618 // now we have to determine
619 // 1) which pin correspond to which phase of the bldc driver
620 // 2) if the currents measured have good polarity
621 //
622 // > when we apply a voltage to a phase A of the driver what we expect to measure is the current I on the phase A
623 // and -I on the phase C
624
625 // find the highest magnitude in A
626 // and make sure it's around the same as the C current (if the phase C is measured)
627
628 float ca[3] = {fabs(c.a), fabs(c.b), fabs(c.c)};
629 if(c.a && c.c){
630 // if a and mid-phase c measured
631 // verify that they have almost the same magnitude
632 if((fabs(c.a) - fabs(c.c)) > 0.1f){
633 SIMPLEFOC_DEBUG("CS: Err A-C currents not equal!");
634 return 0;
635 }
636 }else if(c.b && c.c){
637 // if a and mid-phase c measured
638 // verify that they have almost the same magnitude
639 if((fabs(c.a) - fabs(c.c)) > 0.1f){
640 SIMPLEFOC_DEBUG("CS: Err B-C currents not equal!");
641 return 0;
642 }else{
643 // if the current are equal
644 // switch phase A and B
645 SIMPLEFOC_DEBUG("CS: Switch A-B");
646 _swap(pinA, pinB);
649 _swap(c.a, c.b);
650 phases_switched = true; // signal that pins have been switched
651 }
652 }else if(c.a && c.b){
653 // check if one is significantly higher than the other
654 if(fabs(fabs(c.a) - fabs(c.b)) < 0.1f){
655 SIMPLEFOC_DEBUG("CS: Err A-B currents zero!");
656 return 0;
657 }else{
658 // if they are not equal take the highest as A
659 if (fabs(c.a) < fabs(c.b)){
660 // switch phase A and B
661 SIMPLEFOC_DEBUG("CS: Switch A-B");
662 _swap(pinA, pinB);
665 _swap(c.a, c.b);
666 phases_switched = true; // signal that pins have been switched
667
668 }
669 }
670 }
671 // if we get here, phase A is aligned
672 // check if the current is negative and invert the gain if so
673 if( _sign(c.a) < 0 ){
674 SIMPLEFOC_DEBUG("CS: Inv A");
675 gain_a *= -1;
676 phases_inverted = true; // signal that pins have been inverted
677 }
678
679 // at this point the driver's phase A is aligned with the ADC pinA
680 // and the pin B should be the phase B
681
682 // set phase B active and phases A down
683 // ramp 300ms
684 for(int i=0; i < 100; i++){
685 bldc_driver->setPwm(0, voltage/100.0*((float)i), 0);
686 _delay(3);
687 }
688 _delay(500);
690 bldc_driver->setPwm(0, 0, 0);
691
692 // check if currents are to low (lower than 100mA)
693 if((fabs(c.a) < 0.1f) && (fabs(c.b) < 0.1f) && (fabs(c.c) < 0.1f)){
694 SIMPLEFOC_DEBUG("CS: Err too low current, rise voltage!");
695 return 0; // measurement current too low
696 }
697
698 // check the phase B
699 // find the highest magnitude in c
700 // and make sure it's around the same as the C current (if the phase C is measured)
701 float cb[3] = {fabs(c.a), fabs(c.b), fabs(c.c)};
702 if(c.b && c.c){
703 // if b and mid-phase c measured
704 // verify that they have almost the same magnitude
705 if((fabs(c.b) - fabs(c.c)) > 0.1f){
706 SIMPLEFOC_DEBUG("CS: Err B-C currents not equal!");
707 return 0;
708 }
709 }else if(c.a && c.b){
710 // check if one is significantly higher than the other
711 if(fabs(fabs(c.a) - fabs(c.b)) < 0.1f){
712 SIMPLEFOC_DEBUG("CS: Err A-B currents zero!");
713 return 0;
714 }
715 }
716
717 // check if b has good polarity
718 if( _sign(c.b) < 0 ){
719 SIMPLEFOC_DEBUG("CS: Inv B");
720 gain_b *= -1;
721 phases_inverted = true; // signal that pins have been inverted
722 }
723
724 // construct the return flag
725 // if success and nothing changed return 1
726 // if the phases have been switched return 2
727 // if the gains have been inverted return 3
728 // if both return 4
729 uint8_t exit_flag = 1;
730 if(phases_switched) exit_flag += 1;
731 if(phases_inverted) exit_flag += 2;
732 return exit_flag;
733}
734
735
@ BLDC
Definition FOCDriver.h:17
@ Hybrid
Definition FOCDriver.h:19
@ Stepper
Definition FOCDriver.h:18
@ voltage
Torque control using voltage.
Definition FOCMotor.h:63
#define SIMPLEFOC_DEBUG(msg,...)
virtual void setPwm(float Ua, float Ub, float Uc)=0
float gain_b
phase B gain
float offset_ic
zero current C voltage value (center of the adc reading)
virtual int driverAlign(float align_voltage, bool modulation_centered=false)
PhaseCurrent_s readAverageCurrents(int N=100)
DriverType driver_type
driver type (BLDC or Stepper)
int pinC
pin C analog pin for current measurement
int alignBLDCDriver(float align_voltage, BLDCDriver *driver, bool modulation_centered)
FOCDriver * driver
driver link
int alignStepperDriver(float align_voltage, StepperDriver *driver, bool modulation_centered)
virtual void enable()
int alignHybridDriver(float align_voltage, BLDCDriver *driver, bool modulation_centered)
bool skip_align
variable signaling that the phase current direction should be verified during initFOC()
DQCurrent_s getDQCurrents(ABCurrent_s current, float angle_el)
float gain_c
phase C gain
virtual PhaseCurrent_s getPhaseCurrents()=0
float gain_a
phase A gain
int pinB
pin B analog pin for current measurement
int pinA
pin A analog pin for current measurement
virtual float getDCCurrent(float angle_el=0)
virtual void disable()
float offset_ib
zero current B voltage value (center of the adc reading)
ABCurrent_s getABCurrents(PhaseCurrent_s current)
float offset_ia
zero current A voltage value (center of the adc reading)
DQCurrent_s getFOCCurrents(float angle_el)
void linkDriver(FOCDriver *driver)
virtual DriverType type()=0
float voltage_limit
limiting voltage set to the motor
Definition FOCDriver.h:37
virtual void setPwm(float Ua, float Ub)=0
float a
Definition foc_utils.cpp:59
float float * c
Definition foc_utils.cpp:43
#define _sign(a)
Definition foc_utils.h:7
#define _2_SQRT3
Definition foc_utils.h:20
#define _swap(a, b)
Definition foc_utils.h:17
#define _1_SQRT3
Definition foc_utils.h:22
#define _sqrt(a)
Definition foc_utils.h:12
#define _UNUSED(v)
Definition foc_utils.h:14
#define _isset(a)
Definition foc_utils.h:13
void _sincos(float a, float *s, float *c)
float alpha
Definition foc_utils.h:57
float beta
Definition foc_utils.h:58
float q
Definition foc_utils.h:46
float d
Definition foc_utils.h:45
float c
Definition foc_utils.h:68
float a
Definition foc_utils.h:66
float b
Definition foc_utils.h:67
void _delay(unsigned long ms)
Definition time_utils.cpp:5