SimpleFOClibrary  2.1
InlineCurrentSense.cpp
Go to the documentation of this file.
1 #include "InlineCurrentSense.h"
2 // InlineCurrentSensor constructor
3 // - shunt_resistor - shunt resistor value
4 // - gain - current-sense op-amp gain
5 // - phA - A phase adc pin
6 // - phB - B phase adc pin
7 // - phC - C phase adc pin (optional)
8 InlineCurrentSense::InlineCurrentSense(float _shunt_resistor, float _gain, int _pinA, int _pinB, int _pinC){
9  pinA = _pinA;
10  pinB = _pinB;
11  pinC = _pinC;
12 
13  shunt_resistor = _shunt_resistor;
14  amp_gain = _gain;
15  volts_to_amps_ratio = 1.0 /_shunt_resistor / _gain; // volts to amps
16  // gains for each phase
17  gain_a = volts_to_amps_ratio;
18  gain_b = volts_to_amps_ratio;
19  gain_c = volts_to_amps_ratio;
20 }
21 
22 // Inline sensor init function
24  // configure ADC variables
25  _configureADC(pinA,pinB,pinC);
26  // calibrate zero offsets
27  calibrateOffsets();
28 }
29 // Function finding zero offsets of the ADC
30 void InlineCurrentSense::calibrateOffsets(){
31  // find adc offset = zero current voltage
32  offset_ia =0;
33  offset_ib= 0;
34  offset_ic= 0;
35  // read the adc voltage 1000 times ( arbitrary number )
36  for (int i = 0; i < 1000; i++) {
37  offset_ia += _readADCVoltage(pinA);
38  offset_ib += _readADCVoltage(pinB);
39  if(_isset(pinC)) offset_ic += _readADCVoltage(pinC);
40  _delay(1);
41  }
42  // calculate the mean offsets
43  offset_ia = offset_ia / 1000.0;
44  offset_ib = offset_ib / 1000.0;
45  if(_isset(pinC)) offset_ic = offset_ic / 500.0;
46 }
47 
48 // read all three phase currents (if possible 2 or 3)
50  PhaseCurrent_s current;
51  current.a = (_readADCVoltage(pinA) - offset_ia)*gain_a;// amps
52  current.b = (_readADCVoltage(pinB) - offset_ib)*gain_b;// amps
53  current.c = (!_isset(pinC)) ? 0 : (_readADCVoltage(pinC) - offset_ic)*gain_c; // amps
54  return current;
55 }
56 // Function synchronizing current sense with motor driver.
57 // for in-line sensig no such thing is necessary
59  return 1;
60 }
61 
62 // Function aligning the current sense with motor driver
63 // if all pins are connected well none of this is really necessary! - can be avoided
64 // returns flag
65 // 0 - fail
66 // 1 - success and nothing changed
67 // 2 - success but pins reconfigured
68 // 3 - success but gains inverted
69 // 4 - success but pins reconfigured and gains inverted
71  int exit_flag = 1;
72  if(skip_align) return exit_flag;
73 
74  // set phase A active and phases B and C down
75  driver->setPwm(voltage, 0, 0);
76  _delay(200);
78  // read the current 100 times ( arbitrary number )
79  for (int i = 0; i < 100; i++) {
81  c.a = c.a*0.6 + 0.4*c1.a;
82  c.b = c.b*0.6 + 0.4*c1.b;
83  c.c = c.c*0.6 + 0.4*c1.c;
84  _delay(3);
85  }
86  driver->setPwm(0, 0, 0);
87  // align phase A
88  float ab_ratio = fabs(c.a / c.b);
89  float ac_ratio = c.c ? fabs(c.a / c.c) : 0;
90  if( ab_ratio > 1.5 ){ // should be ~2
91  gain_a *= _sign(c.a);
92  }else if( ab_ratio < 0.7 ){ // should be ~0.5
93  // switch phase A and B
94  int tmp_pinA = pinA;
95  pinA = pinB;
96  pinB = tmp_pinA;
97  gain_a *= _sign(c.b);
98  exit_flag = 2; // signal that pins have been switched
99  }else if(_isset(pinC) && ac_ratio < 0.7 ){ // should be ~0.5
100  // switch phase A and C
101  int tmp_pinA = pinA;
102  pinA = pinC;
103  pinC= tmp_pinA;
104  gain_a *= _sign(c.c);
105  exit_flag = 2;// signal that pins have been switched
106  }else{
107  // error in current sense - phase either not measured or bad connection
108  return 0;
109  }
110 
111  // set phase B active and phases A and C down
112  driver->setPwm(0, voltage, 0);
113  _delay(200);
114  c = getPhaseCurrents();
115  // read the current 50 times
116  for (int i = 0; i < 100; i++) {
118  c.a = c.a*0.6 + 0.4*c1.a;
119  c.b = c.b*0.6 + 0.4*c1.b;
120  c.c = c.c*0.6 + 0.4*c1.c;
121  _delay(3);
122  }
123  driver->setPwm(0, 0, 0);
124  float ba_ratio = fabs(c.b/c.a);
125  float bc_ratio = c.c ? fabs(c.b / c.c) : 0;
126  if( ba_ratio > 1.5 ){ // should be ~2
127  gain_b *= _sign(c.b);
128  }else if( ba_ratio < 0.7 ){ // it should be ~0.5
129  // switch phase A and B
130  int tmp_pinB = pinB;
131  pinB = pinA;
132  pinA = tmp_pinB;
133  gain_b *= _sign(c.a);
134  exit_flag = 2; // signal that pins have been switched
135  }else if(_isset(pinC) && bc_ratio < 0.7 ){ // should be ~0.5
136  // switch phase A and C
137  int tmp_pinB = pinB;
138  pinB = pinC;
139  pinC = tmp_pinB;
140  gain_b *= _sign(c.c);
141  exit_flag = 2; // signal that pins have been switched
142  }else{
143  // error in current sense - phase either not measured or bad connection
144  return 0;
145  }
146 
147  // if phase C measured
148  if(_isset(pinC)){
149  // set phase B active and phases A and C down
150  driver->setPwm(0, 0, voltage);
151  _delay(200);
152  c = getPhaseCurrents();
153  // read the adc voltage 500 times ( arbitrary number )
154  for (int i = 0; i < 50; i++) {
156  c.c = (c.c+c1.c)/50.0;
157  }
158  driver->setPwm(0, 0, 0);
159  gain_c *= _sign(c.c);
160  }
161 
162  if(gain_a < 0 || gain_b < 0 || gain_c < 0) exit_flag +=2;
163  // exit flag is either
164  // 0 - fail
165  // 1 - success and nothing changed
166  // 2 - success but pins reconfigured
167  // 3 - success but gains inverted
168  // 4 - success but pins reconfigured and gains inverted
169  return exit_flag;
170 }
171 
BLDCDriver
Definition: BLDCDriver.h:6
InlineCurrentSense::gain_b
int gain_b
phase B gain
Definition: InlineCurrentSense.h:33
voltage
@ voltage
Torque control using voltage.
Definition: FOCMotor.h:39
_isset
#define _isset(a)
Definition: foc_utils.h:11
_delay
void _delay(unsigned long ms)
Definition: time_utils.cpp:5
CurrentSense::skip_align
bool skip_align
variable signaling that the phase current direction should be verified during initFOC()
Definition: CurrentSense.h:28
_configureADC
void _configureADC(const int pinA, const int pinB, const int pinC=NOT_SET)
Definition: current_sense/hardware_specific/generic_mcu.cpp:43
BLDCDriver::setPwm
virtual void setPwm(float Ua, float Ub, float Uc)=0
InlineCurrentSense::gain_c
int gain_c
phase C gain
Definition: InlineCurrentSense.h:34
InlineCurrentSense::InlineCurrentSense
InlineCurrentSense(float shunt_resistor, float gain, int pinA, int pinB, int pinC=NOT_SET)
Definition: InlineCurrentSense.cpp:8
InlineCurrentSense::getPhaseCurrents
PhaseCurrent_s getPhaseCurrents() override
Definition: InlineCurrentSense.cpp:49
InlineCurrentSense::init
void init() override
Definition: InlineCurrentSense.cpp:23
_readADCVoltage
float _readADCVoltage(const int pinA)
Definition: current_sense/hardware_specific/generic_mcu.cpp:36
InlineCurrentSense::driverAlign
int driverAlign(BLDCDriver *driver, float voltage) override
Definition: InlineCurrentSense.cpp:70
PhaseCurrent_s
Definition: foc_utils.h:40
PhaseCurrent_s::b
float b
Definition: foc_utils.h:42
InlineCurrentSense::driverSync
int driverSync(BLDCDriver *driver) override
Definition: InlineCurrentSense.cpp:58
PhaseCurrent_s::a
float a
Definition: foc_utils.h:41
InlineCurrentSense.h
InlineCurrentSense::gain_a
int gain_a
phase A gain
Definition: InlineCurrentSense.h:32
_sign
#define _sign(a)
Definition: foc_utils.h:7
PhaseCurrent_s::c
float c
Definition: foc_utils.h:43