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 (¤t_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