Skip to content

Commit 3f6a73e

Browse files
committed
current sense alignement
1 parent 26215fb commit 3f6a73e

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/**
2+
* This is an example code for visual aligning current sense and the driver phases as well
3+
* it is used to test the current sense implementation.
4+
*
5+
* In this example it uses the BLDCMotor and BLDCDriver3PWM classes to control a BLDC motor
6+
* and the InlineCurrentSense class to read the phase currents.
7+
* > In your application you can use any other motor, driver and current sense implementation.
8+
* > The rest of the code will stay the same
9+
*
10+
* The example uses the teleplot (https://teleplot.fr) service to visualize the phase currents and voltages.
11+
* Its really awesome tool and you can use it to visualize any data you want.
12+
*/
13+
#include <SimpleFOC.h>
14+
15+
// BLDC motor & driver instance
16+
// NOTE: replace with your motor and driver configuration
17+
BLDCMotor motor = BLDCMotor(11);
18+
BLDCDriver3PWM driver = BLDCDriver3PWM(6, 10, 5, 8);
19+
20+
// Current sense instance
21+
// NOTE: replace with your current sense configuration
22+
// inline current sensor instance
23+
// ACS712-05B has the resolution of 0.185mV per Amp
24+
InlineCurrentSense current_sense = InlineCurrentSense(185.0f, A0, A2);
25+
// or some other current sense
26+
// LowsideCurrentSense current_sense = LowsideCurrentSense(185.0f, A0, A2); // ex. lowside current sense
27+
28+
// commander communication instance
29+
Commander command = Commander(Serial);
30+
31+
32+
bool start = false; // flag to start printing phase currents and voltages
33+
float frequency = 10000; // frequency of printing phase currents and voltages
34+
35+
void doStart(char* cmd){
36+
// toggle the start flag
37+
start = !start;
38+
if(start){
39+
SIMPLEFOC_DEBUG("Start printing phase currents and voltages");
40+
} else {
41+
SIMPLEFOC_DEBUG("Stop printing phase currents and voltages");
42+
}
43+
}
44+
45+
void doCurrentA(char* cmd){
46+
SIMPLEFOC_DEBUG("Inverted cs A gain");
47+
current_sense.gain_a = -current_sense.gain_a;
48+
SIMPLEFOC_DEBUG("New gain A: ", current_sense.gain_a);
49+
}
50+
void doCurrentB(char* cmd){
51+
SIMPLEFOC_DEBUG("Inverted cs B gain");
52+
current_sense.gain_b = -current_sense.gain_b;
53+
SIMPLEFOC_DEBUG("New gain B: ", current_sense.gain_b);
54+
}
55+
void doCurrentC(char* cmd){
56+
SIMPLEFOC_DEBUG("Inverted cs C gain");
57+
current_sense.gain_c = -current_sense.gain_c;
58+
SIMPLEFOC_DEBUG("New gain C: ", current_sense.gain_c);
59+
}
60+
61+
void doMotorLimit(char* cmd){
62+
// set the voltage limit for the motor
63+
command.scalar(&motor.voltage_limit, cmd);
64+
}
65+
66+
void doTarget(char* cmd){
67+
// set the target value for the motor
68+
command.scalar(&motor.target, cmd);
69+
}
70+
71+
void doFrequency(char* cmd){
72+
// set the frequency of printing phase currents and voltages
73+
command.scalar(&frequency, cmd);
74+
}
75+
76+
void setup() {
77+
78+
// use monitoring with serial
79+
Serial.begin(115200);
80+
// enable more verbose output for debugging
81+
// comment out if not needed
82+
SimpleFOCDebug::enable(&Serial);
83+
84+
// driver config
85+
// power supply voltage [V]
86+
driver.voltage_power_supply = 20;
87+
driver.init();
88+
// link driver
89+
motor.linkDriver(&driver);
90+
// link current sense and the driver
91+
current_sense.linkDriver(&driver);
92+
93+
// set control loop type to be used
94+
motor.controller = MotionControlType::velocity_openloop;
95+
96+
motor.voltage_limit = 1; // voltage limit for the motor
97+
98+
// initialise motor
99+
motor.init();
100+
101+
// current sense init and linking
102+
current_sense.init();
103+
motor.linkCurrentSense(&current_sense);
104+
105+
// align encoder and start FOC
106+
motor.initFOC();
107+
108+
// set the inital target value
109+
motor.target = 0.5;
110+
111+
112+
// subscribe motor to the commander
113+
//command.add('T', doMotion, "motion control");
114+
command.add('A', doCurrentA, "Invert cs A gain");
115+
command.add('B', doCurrentB, "Invert cs B gain");
116+
command.add('C', doCurrentC, "Invert cs C gain");
117+
command.add('L', doMotorLimit, "Set motor voltage limit");
118+
command.add('T', doTarget, "Set motor target");
119+
command.add('S', doStart, "Start/Stop printing phase currents and voltages");
120+
command.add('F', doFrequency, "Set frequency of printing phase currents and voltages");
121+
122+
SIMPLEFOC_DEBUG("To use this example:");
123+
SIMPLEFOC_DEBUG(" - use 'L' to control the motor voltage limit");
124+
SIMPLEFOC_DEBUG(" - use 'T' to set the motor target");
125+
SIMPLEFOC_DEBUG(" - use 'A', 'B', 'C' to invert current sense gains");
126+
SIMPLEFOC_DEBUG(" - use 'F' to set frequency of printing phase currents and voltages (100Hz by default)");
127+
SIMPLEFOC_DEBUG(" - use 'S' to start/stop printing phase currents and voltages");
128+
SIMPLEFOC_DEBUG("IMPORTANT: Use teleplot to visualize the phase currents and voltages: https://teleplot.fr/");
129+
130+
_delay(1000);
131+
132+
}
133+
134+
float normalize_voltage(float v){
135+
return (v - driver.voltage_power_supply/2.0)/motor.voltage_limit;
136+
}
137+
138+
float max_current = 0.0f; // max current for normalization
139+
LowPassFilter lp_filter_maxc(0.3f); // low pass filter for current normalization
140+
void normalize_currents(PhaseCurrent_s& c, float& max_current){
141+
static unsigned long timestamp = _micros();
142+
// normalize current to the max current
143+
144+
float m_current = 0.0f;
145+
if(fabs(c.a) > m_current) m_current = fabs(c.a);
146+
if(fabs(c.b) > m_current) m_current = fabs(c.b);
147+
if(fabs(c.c) > m_current) m_current = fabs(c.c);
148+
// filter the max current
149+
max_current = lp_filter_maxc(m_current);
150+
151+
c.a = c.a / max_current;
152+
c.b = c.b / max_current;
153+
c.c = c.c / max_current;
154+
}
155+
156+
unsigned long t = _micros();
157+
158+
void loop() {
159+
motor.loopFOC();
160+
motor.move();
161+
162+
// print each
163+
if( start & (_micros() - t > (1.0/frequency * 1e6))){
164+
// read phase currents
165+
PhaseCurrent_s currents = current_sense.getPhaseCurrents();
166+
// normalize currents
167+
normalize_currents(currents, max_current);
168+
// print phase currents
169+
SIMPLEFOC_DEBUG(">c.a:",currents.a);
170+
SIMPLEFOC_DEBUG(">c.b:",currents.b);
171+
SIMPLEFOC_DEBUG(">c.c:",currents.c);
172+
// print phase voltages
173+
SIMPLEFOC_DEBUG(">v.a:",normalize_voltage(motor.Ua));
174+
SIMPLEFOC_DEBUG(">v.b:",normalize_voltage(motor.Ub));
175+
SIMPLEFOC_DEBUG(">v.c:",normalize_voltage(motor.Uc));
176+
t = _micros();
177+
}
178+
179+
// user communication
180+
command.run();
181+
}

0 commit comments

Comments
 (0)