|
| 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 9 |
| 19 | +#define INH_B 10 |
| 20 | +#define INH_C 11 |
| 21 | +#define EN_GATE 7 |
| 22 | +#define M_PWM A1 |
| 23 | +#define M_OC A2 |
| 24 | +#define OC_ADJ A3 |
| 25 | + |
| 26 | +// motor instance |
| 27 | +BLDCMotor motor = BLDCMotor(INH_A, INH_B, INH_C, 11, EN_GATE); |
| 28 | + |
| 29 | +// encoder instance |
| 30 | +Encoder encoder = Encoder(2, 3, 8192); |
| 31 | + |
| 32 | +// Interrupt routine intialisation |
| 33 | +// channel A and B callbacks |
| 34 | +void doA(){encoder.handleA();} |
| 35 | +void doB(){encoder.handleB();} |
| 36 | + |
| 37 | +void setup() { |
| 38 | + |
| 39 | + // initialize encoder sensor hardware |
| 40 | + encoder.init(); |
| 41 | + encoder.enableInterrupts(doA, doB); |
| 42 | + // link the motor to the sensor |
| 43 | + motor.linkSensor(&encoder); |
| 44 | + |
| 45 | + // DRV8302 specific code |
| 46 | + // M_OC - enable overcurrent protection |
| 47 | + pinMode(M_OC,OUTPUT); |
| 48 | + digitalWrite(M_OC,LOW); |
| 49 | + // M_PWM - enable 3pwm mode |
| 50 | + pinMode(M_PWM,OUTPUT); |
| 51 | + digitalWrite(M_PWM,HIGH); |
| 52 | + // OD_ADJ - set the maximum overcurrent limit possible |
| 53 | + // Better option would be to use voltage divisor to set exact value |
| 54 | + pinMode(OC_ADJ,OUTPUT); |
| 55 | + digitalWrite(OC_ADJ,HIGH); |
| 56 | + |
| 57 | + // choose FOC modulation |
| 58 | + motor.foc_modulation = FOCModulationType::SpaceVectorPWM; |
| 59 | + |
| 60 | + // power supply voltage [V] |
| 61 | + motor.voltage_power_supply = 12; |
| 62 | + |
| 63 | + // set control loop type to be used |
| 64 | + motor.controller = ControlType::voltage; |
| 65 | + |
| 66 | + // contoller configuration based on the controll type |
| 67 | + motor.PI_velocity.P = 0.2; |
| 68 | + motor.PI_velocity.I = 20; |
| 69 | + // default voltage_power_supply |
| 70 | + motor.PI_velocity.voltage_limit = 12; |
| 71 | + |
| 72 | + // velocity low pass filtering time constant |
| 73 | + motor.LPF_velocity.Tf = 0.01; |
| 74 | + |
| 75 | + // angle loop controller |
| 76 | + motor.P_angle.P = 20; |
| 77 | + // angle loop velocity limit |
| 78 | + motor.P_angle.velocity_limit = 50; |
| 79 | + |
| 80 | + // use monitoring with serial for motor init |
| 81 | + // monitoring port |
| 82 | + Serial.begin(115200); |
| 83 | + // comment out if not needed |
| 84 | + motor.useMonitoring(Serial); |
| 85 | + |
| 86 | + // initialise motor |
| 87 | + motor.init(); |
| 88 | + // align encoder and start FOC |
| 89 | + motor.initFOC(); |
| 90 | + |
| 91 | + // set the inital target value |
| 92 | + motor.target = 2; |
| 93 | + |
| 94 | + |
| 95 | + Serial.println("Full control example: "); |
| 96 | + Serial.println("Run user commands to configure and the motor (find the full command list in docs.simplefoc.com) \n "); |
| 97 | + Serial.println("Initial motion control loop is voltage loop."); |
| 98 | + Serial.println("Initial target voltage 2V."); |
| 99 | + |
| 100 | + _delay(1000); |
| 101 | +} |
| 102 | + |
| 103 | + |
| 104 | +void loop() { |
| 105 | + // iterative setting FOC phase voltage |
| 106 | + motor.loopFOC(); |
| 107 | + |
| 108 | + // iterative function setting the outter loop target |
| 109 | + // velocity, position or voltage |
| 110 | + // if tatget not set in parameter uses motor.target variable |
| 111 | + motor.move(); |
| 112 | + |
| 113 | + // user communication |
| 114 | + motor.command(serialReceiveUserCommand()); |
| 115 | +} |
| 116 | + |
| 117 | +// utility function enabling serial communication the user |
| 118 | +String serialReceiveUserCommand() { |
| 119 | + |
| 120 | + // a string to hold incoming data |
| 121 | + static String received_chars; |
| 122 | + |
| 123 | + String command = ""; |
| 124 | + |
| 125 | + while (Serial.available()) { |
| 126 | + // get the new byte: |
| 127 | + char inChar = (char)Serial.read(); |
| 128 | + // add it to the string buffer: |
| 129 | + received_chars += inChar; |
| 130 | + |
| 131 | + // end of user input |
| 132 | + if (inChar == '\n') { |
| 133 | + |
| 134 | + // execute the user command |
| 135 | + command = received_chars; |
| 136 | + |
| 137 | + // reset the command buffer |
| 138 | + received_chars = ""; |
| 139 | + } |
| 140 | + } |
| 141 | + return command; |
| 142 | +} |
| 143 | + |
0 commit comments