Skip to content

Commit 18fbfe6

Browse files
committed
added an example
1 parent cec8df0 commit 18fbfe6

6 files changed

Lines changed: 136 additions & 14 deletions

File tree

.github/workflows/arduino.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ jobs:
3333
esp32_current_control_low_side, stm32_spi_alt_example, esp32_spi_alt_example,
3434
B_G431B_ESC1, odrive_example_spi, odrive_example_encoder, single_full_control_example,
3535
double_full_control_example, stm32_current_control_low_side, open_loop_velocity_6pwm,
36-
efr32_hall_sensor_velocity_6pwm, efr32_open_loop_velocity_6pwm, efr32_torque_velocity_6pwm
36+
efr32_hall_sensor_velocity_6pwm, efr32_open_loop_velocity_6pwm, efr32_torque_velocity_6pwm,
37+
custom_motion_control
3738

3839
- arduino-boards-fqbn: arduino:sam:arduino_due_x # arduino due - one full example
3940
sketch-names: single_full_control_example.ino

.github/workflows/stm32.yml

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ jobs:
1616
strategy:
1717
matrix:
1818
arduino-boards-fqbn:
19-
- STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 # stm32 bluepill
20-
- STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_F411RE # stm32 nucleo
21-
- STMicroelectronics:stm32:Nucleo_144:pnum=NUCLEO_F746ZG # stm32 nucleo f746zg
22-
- STMicroelectronics:stm32:GenF4:pnum=GENERIC_F405RGTX # stm32f405 - odrive
23-
- STMicroelectronics:stm32:GenL4:pnum=GENERIC_L475RGTX # stm32l475
24-
- STMicroelectronics:stm32:Disco:pnum=B_G431B_ESC1 # B-G431-ESC1
19+
- STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 # stm32 bluepill
20+
- STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_F411RE # stm32 nucleo
21+
- STMicroelectronics:stm32:Nucleo_144:pnum=NUCLEO_F746ZG # stm32 nucleo f746zg
22+
- STMicroelectronics:stm32:GenF4:pnum=GENERIC_F405RGTX # stm32f405 - odrive
23+
- STMicroelectronics:stm32:GenL4:pnum=GENERIC_L475RGTX # stm32l475
24+
- STMicroelectronics:stm32:Disco:pnum=B_G431B_ESC1 # B-G431-ESC1
25+
- STMicroelectronics:stm32:Nucleo_144:pnum=NUCLEO_H723ZG # stm32h7
26+
- STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_G431RB # stm32g4
2527

2628
include:
2729
- arduino-boards-fqbn: STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 # bluepill - hs examples
@@ -45,12 +47,19 @@ jobs:
4547

4648
- arduino-boards-fqbn: STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_F411RE # nucleo one full example
4749
platform-url: https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json
48-
sketch-names: single_full_control_example.ino, stm32_spi_alt_example.ino, double_full_control_example.ino, stm32_current_control_low_side.ino
50+
sketch-names: single_full_control_example.ino, stm32_spi_alt_example.ino, double_full_control_example.ino, stm32_current_control_low_side.ino, custom_motion_control.ino
4951

5052
- arduino-boards-fqbn: STMicroelectronics:stm32:Nucleo_144:pnum=NUCLEO_F746ZG # nucleo f7 one full example
5153
platform-url: https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json
52-
sketch-names: single_full_control_example.ino, stm32_spi_alt_example.ino, double_full_control_example.ino, stm32_current_control_low_side.ino
53-
54+
sketch-names: single_full_control_example.ino, stm32_spi_alt_example.ino, double_full_control_example.ino, stm32_current_control_low_side.ino, custom_motion_control.ino
55+
56+
- arduino-boards-fqbn: STMicroelectronics:stm32:Nucleo_144:pnum=NUCLEO_H723ZG # nucleo h7 one full example
57+
platform-url: https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json
58+
sketch-names: single_full_control_example.ino, stm32_spi_alt_example.ino, double_full_control_example.ino, stm32_current_control_low_side.ino, custom_motion_control.ino
59+
60+
- arduino-boards-fqbn: STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_G431RB # stm32g4 one full example
61+
platform-url: https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json
62+
sketch-names: single_full_control_example.ino, stm32_spi_alt_example.ino, double_full_control_example.ino, stm32_current_control_low_side.ino, custom_motion_control.ino
5463

5564
# Do not cancel all jobs / architectures if one job fails
5665
fail-fast: false
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
2+
#include <Arduino.h>
3+
#include <SimpleFOC.h>
4+
#include "current_sense/hardware_specific/stm32/stm32_mcu.h"
5+
6+
7+
// BLDC motor & driver instance
8+
BLDCMotor motor = BLDCMotor(7);
9+
BLDCDriver3PWM driver = BLDCDriver3PWM(D6, D10, D5, D8);
10+
11+
// encoder instance
12+
MagneticSensorSPI sensor = MagneticSensorSPI(AS5048_SPI, D4);
13+
14+
// inline current sensor instance
15+
// INA240A1 (gain 20V/V) and 5mOhm shunt resistor
16+
LowsideCurrentSense current_sense = LowsideCurrentSense(0.005, 20.0f, A0, _NC, A3);
17+
18+
// commander communication instance
19+
Commander command = Commander(Serial);
20+
// void doMotion(char* cmd){ command.motion(&motor, cmd); }
21+
void doMotor(char* cmd){ command.motor(&motor, cmd); }
22+
23+
24+
// custom PID controller instance for the custom control method
25+
// P controller with gain of 1.0f, no integral or derivative gain
26+
PIDController custom_PID = PIDController(1.0f, 0, 0);
27+
// custom motion control method
28+
float positionPControl(FOCMotor* motor, float target){
29+
// simple proportional position control
30+
float error = target - motor->shaft_angle;
31+
// set the PID output limit to the motor current limit
32+
custom_PID.limit = motor->current_limit;
33+
return custom_PID(error); // return current command based on the error
34+
}
35+
36+
// optional add the PID to command to be able to tune it in runtime
37+
void doPID(char* cmd){ command.pid(&custom_PID, cmd); }
38+
39+
void setup() {
40+
// use monitoring with serial
41+
Serial.begin(115200);
42+
// enable more verbose output for debugging
43+
// comment out if not needed
44+
SimpleFOCDebug::enable(&Serial);
45+
46+
// initialize sensor hardware
47+
sensor.init(&SPI);
48+
motor.linkSensor(&sensor);
49+
50+
// driver config
51+
// power supply voltage [V]
52+
driver.voltage_power_supply = 20;
53+
driver.init();
54+
// link driver
55+
motor.linkDriver(&driver);
56+
// link current sense and the driver
57+
current_sense.linkDriver(&driver);
58+
59+
// set the custom control method as the position P control
60+
motor.setCustomMotionControlMethod(positionPControl);
61+
// set control loop type to be used
62+
motor.controller = MotionControlType::custom;
63+
// set the torque control type to voltage control (default is voltage control)
64+
motor.torque_controller = TorqueControlType::foc_current;
65+
66+
// velocity low pass filtering time constant
67+
motor.LPF_velocity.Tf = 0.01f;
68+
69+
// angle loop controller
70+
motor.P_angle.P = 20;
71+
// angle loop velocity limit
72+
motor.velocity_limit = 20;
73+
motor.voltage_sensor_align = 1.0f;
74+
75+
// comment out if not needed
76+
motor.useMonitoring(Serial);
77+
motor.monitor_downsample = 0; // disable intially
78+
motor.monitor_variables = _MON_TARGET | _MON_VEL | _MON_ANGLE; // monitor target velocity and angle
79+
80+
// current sense init and linking
81+
current_sense.init();
82+
motor.linkCurrentSense(&current_sense);
83+
84+
// initialise motor
85+
motor.init();
86+
// align encoder and start FOC
87+
motor.initFOC();
88+
89+
// subscribe motor to the commander
90+
//command.add('T', doMotion, "motion control"); // a bit less resouce intensive
91+
command.add('M', doMotor, "motor");
92+
command.add('C', doPID, "custom PID");
93+
94+
_delay(1000);
95+
}
96+
97+
void loop() {
98+
// iterative setting FOC phase voltage
99+
motor.loopFOC();
100+
101+
// iterative function setting the outter loop target
102+
motor.move();
103+
104+
// // motor monitoring
105+
motor.monitor();
106+
107+
// user communication
108+
command.run();
109+
}

src/common/base_classes/FOCMotor.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,8 @@ void FOCMotor::updateMotionControlType(MotionControlType new_motion_controller)
521521
target = 0;
522522
break;
523523
default:
524+
// if torque control set target to zero
525+
target = 0;
524526
break;
525527
}
526528

@@ -753,6 +755,7 @@ void FOCMotor::move(float new_target) {
753755
// user makes sure to use it with appropriate torque control mode
754756
if(customMotionControlCallback)
755757
current_sp = customMotionControlCallback(this, target);
758+
break;
756759
}
757760
}
758761

src/common/pid.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,18 @@ float PIDController::operator() (float error){
3737
// u_ik = u_ik_1 + I*Ts/2*(ek + ek_1)
3838
float integral = integral_prev + I*dt*0.5f*(error + error_prev);
3939
// antiwindup - limit the output
40-
integral = _constrain(integral, -limit, limit);
40+
if(_isset(limit)) integral = _constrain(integral, -limit, limit);
4141
// Discrete derivation
4242
// u_dk = D(ek - ek_1)/Ts
4343
float derivative = D*(error - error_prev)/dt;
4444

4545
// sum all the components
4646
float output = proportional + integral + derivative;
4747
// antiwindup - limit the output variable
48-
output = _constrain(output, -limit, limit);
48+
if(_isset(limit)) output = _constrain(output, -limit, limit);
4949

5050
// if output ramp defined
51-
if(output_ramp > 0){
51+
if(_isset(output_ramp) && output_ramp > 0){
5252
// limit the acceleration by ramping the output
5353
float output_rate = (output - output_prev)/dt;
5454
if (output_rate > output_ramp)

src/common/pid.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class PIDController
2525
* @note Sampling time can be changed dynamically as well by modifying the
2626
* variable Ts in runtime.
2727
*/
28-
PIDController(float P, float I, float D, float ramp, float limit, float sampling_time = NOT_SET);
28+
PIDController(float P, float I, float D, float ramp = NOT_SET, float limit = NOT_SET, float sampling_time = NOT_SET);
2929
~PIDController() = default;
3030

3131
float operator() (float error);

0 commit comments

Comments
 (0)