| 
 | 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