1
+ /* *
2
+ * Comprehensive BLDC motor control example using encoder and the DRV8302 board
3
+ *
4
+ * Using serial terminal user can send motor commands and configure the motor and FOC in real-time:
5
+ * - configure PID controller constants
6
+ * - change motion control loops
7
+ * - monitor motor variabels
8
+ * - set target values
9
+ * - check all the configuration values
10
+ *
11
+ * check the https://docs.simplefoc.com for full list of motor commands
12
+ *
13
+ */
14
+ #include < SimpleFOC.h>
15
+
16
+ // DRV8302 pins connections
17
+ // don't forget to connect the common ground pin
18
+ #define INH_A 21
19
+ #define INH_B 19
20
+ #define INH_C 18
21
+
22
+ #define EN_GATE 5
23
+ #define M_PWM 25
24
+ #define M_OC 26
25
+ #define OC_ADJ 12
26
+ #define OC_GAIN 14
27
+
28
+ #define IOUTA 34
29
+ #define IOUTB 35
30
+ #define IOUTC 32
31
+
32
+ // Motor instance
33
+ BLDCMotor motor = BLDCMotor(7 );
34
+ BLDCDriver3PWM driver = BLDCDriver3PWM(INH_A, INH_B, INH_C, EN_GATE);
35
+
36
+ // DRV8302 board has 0.005Ohm shunt resistors and the gain of 12.22 V/V
37
+ LowsideCurrentSense cs = LowsideCurrentSense(0 .005f , 12 .22f , IOUTA, IOUTB, IOUTC);
38
+
39
+ // encoder instance
40
+ Encoder encoder = Encoder(22 , 23 , 500 );
41
+
42
+ // Interrupt routine intialisation
43
+ // channel A and B callbacks
44
+ void doA (){encoder.handleA ();}
45
+ void doB (){encoder.handleB ();}
46
+
47
+
48
+ // commander interface
49
+ Commander command = Commander(Serial);
50
+ void onMotor (char * cmd){ command.motor (&motor, cmd); }
51
+
52
+ void setup () {
53
+
54
+ // initialize encoder sensor hardware
55
+ encoder.init ();
56
+ encoder.enableInterrupts (doA, doB);
57
+ // link the motor to the sensor
58
+ motor.linkSensor (&encoder);
59
+
60
+ // DRV8302 specific code
61
+ // M_OC - enable overcurrent protection
62
+ pinMode (M_OC,OUTPUT);
63
+ digitalWrite (M_OC,LOW);
64
+ // M_PWM - enable 3pwm mode
65
+ pinMode (M_PWM,OUTPUT);
66
+ digitalWrite (M_PWM,HIGH);
67
+ // OD_ADJ - set the maximum overcurrent limit possible
68
+ // Better option would be to use voltage divisor to set exact value
69
+ pinMode (OC_ADJ,OUTPUT);
70
+ digitalWrite (OC_ADJ,HIGH);
71
+ pinMode (OC_GAIN,OUTPUT);
72
+ digitalWrite (OC_GAIN,LOW);
73
+
74
+
75
+ // driver config
76
+ // power supply voltage [V]
77
+ driver.voltage_power_supply = 12 ;
78
+ driver.pwm_frequency = 15000 ;
79
+ driver.init ();
80
+ // link the motor and the driver
81
+ motor.linkDriver (&driver);
82
+ motor.voltage_sensor_align = 0.5 ;
83
+
84
+ // control loop type and torque mode
85
+ motor.torque_controller = TorqueControlType::voltage;
86
+ motor.controller = MotionControlType::torque;
87
+ motor.motion_downsample = 0.0 ;
88
+
89
+ // velocity loop PID
90
+ motor.PID_velocity .P = 0.2 ;
91
+ motor.PID_velocity .I = 5.0 ;
92
+ // Low pass filtering time constant
93
+ motor.LPF_velocity .Tf = 0.02 ;
94
+ // angle loop PID
95
+ motor.P_angle .P = 20.0 ;
96
+ // Low pass filtering time constant
97
+ motor.LPF_angle .Tf = 0.0 ;
98
+ // current q loop PID
99
+ motor.PID_current_q .P = 3.0 ;
100
+ motor.PID_current_q .I = 100.0 ;
101
+ // Low pass filtering time constant
102
+ motor.LPF_current_q .Tf = 0.02 ;
103
+ // current d loop PID
104
+ motor.PID_current_d .P = 3.0 ;
105
+ motor.PID_current_d .I = 100.0 ;
106
+ // Low pass filtering time constant
107
+ motor.LPF_current_d .Tf = 0.02 ;
108
+
109
+ // Limits
110
+ motor.velocity_limit = 100.0 ; // 100 rad/s velocity limit
111
+ motor.voltage_limit = 12.0 ; // 12 Volt limit
112
+ motor.current_limit = 2.0 ; // 2 Amp current limit
113
+
114
+
115
+ // use monitoring with serial for motor init
116
+ // monitoring port
117
+ Serial.begin (115200 );
118
+ // comment out if not needed
119
+ motor.useMonitoring (Serial);
120
+ motor.monitor_variables = _MON_CURR_Q | _MON_CURR_D; // monitor the two currents d and q
121
+ motor.monitor_downsample = 1000 ;
122
+
123
+ // initialise motor
124
+ motor.init ();
125
+
126
+ cs.init ();
127
+ cs.driverSync (&driver);
128
+ // driver 8302 has inverted gains on all channels
129
+ cs.gain_a *=-1 ;
130
+ cs.gain_b *=-1 ;
131
+ cs.gain_c *=-1 ;
132
+ motor.linkCurrentSense (&cs);
133
+
134
+ // align encoder and start FOC
135
+ motor.initFOC ();
136
+
137
+ // set the inital target value
138
+ motor.target = 0 ;
139
+
140
+ // define the motor id
141
+ command.add (' M' , onMotor, " motor" );
142
+
143
+ Serial.println (F (" Full control example: " ));
144
+ Serial.println (F (" Run user commands to configure and the motor (find the full command list in docs.simplefoc.com) \n " ));
145
+ Serial.println (F (" Initial motion control loop is voltage loop." ));
146
+ Serial.println (F (" Initial target voltage 2V." ));
147
+
148
+ _delay (1000 );
149
+ }
150
+
151
+
152
+ void loop () {
153
+ // iterative setting FOC phase voltage
154
+ motor.loopFOC ();
155
+
156
+ // iterative function setting the outter loop target
157
+ motor.move ();
158
+
159
+ // monitoring the state variables
160
+ motor.monitor ();
161
+
162
+ // user communication
163
+ command.run ();
164
+ }
0 commit comments