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