├── README.md └── i2c_motor_control_test.ino /README.md: -------------------------------------------------------------------------------- 1 | # BLDC-Motorcontroller 2 | This is a very simple sketch to control two BLDC motors using the STEVAL-GMBL02V1, SimpleFOC library and Arduino IDE. 3 | Motors are iPower GM3506 with internal AS5048A encoders. 4 | 5 | I'm using Tourqe as MotionControlType and Voltage as TourqeControlType. This is because the STEVAL-GMBL02V1 sadly only offers a single shunt per motor connection, making Current control impossible (using SimpleFOC v2.2.2 at least). 6 | 7 | The controller is managed via I2C connection to a Raspberry Pi and receives relevant speed and steering data. 8 | 9 | # Findings regarding the STEVAL-GMBL02V1 10 | I didn't find much information about the STEVAL-GMBL02V1 online, so i collected everything here in case anyone else might be interested in it. 11 | - The documentation notes "6V to 8.4VDC bus voltage range, which you can increase to 11V". It isn't mentioned again, and should be taken with a grain of salt, as the STSPIN233 driver has an operating voltage between 1.8 and 10V, with 11V being the absolute maximum rating for it. 12 | - I2C can be wired via PB9/SDA and PB8/SCL, or if absolutely neccessary there is another I2C pin in the 10 pin header for the STLink connection. You will need to overwrite the SWD pins for this, so take care. 13 | - BOOT0 is hardwired to GND, so you'll need a small probe to pull it high. 14 | -------------------------------------------------------------------------------- /i2c_motor_control_test.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | Rotary Encoder Wires: 6 | Purple - PWM - Gray 7 | Green - GND - Black 8 | Blue - 5V - White 9 | */ 10 | 11 | #define SENSORPWM1 PB6 12 | #define SENSORPWM2 PB7 13 | 14 | #define LEDPIN PA7 15 | #define SLAVEADDRESS 0x8 16 | #define SDAPIN PB9 17 | #define SCLPIN PB8 18 | 19 | #define SUPPLYVOLTAGE 8.4 20 | #define VOLTAGELIMITDRIVER 6 21 | #define VOLTAGELIMITMOTOR 3 22 | #define MOTORRESISTANCE 5.57 23 | 24 | #define SENSORMINPULSE 7 25 | #define SENSORMAXPULSE 935 26 | 27 | #define POLEPAIRS 11 28 | #define CLOSEDLOOP true 29 | 30 | #define MESSAGESIZE 8 31 | #define MAXTARGETVELOCITY 50 32 | #define MAXTARGETCURRENT 10 33 | #define MAXTARGETVOLTAGE 6 34 | 35 | BLDCMotor motor1 = BLDCMotor(POLEPAIRS, MOTORRESISTANCE); 36 | BLDCDriver3PWM driver1 = BLDCDriver3PWM(PC0, PC1, PC2, PC13); 37 | MagneticSensorPWM sensor1 = MagneticSensorPWM(SENSORPWM1, SENSORMINPULSE, SENSORMAXPULSE); 38 | 39 | BLDCMotor motor2 = BLDCMotor(POLEPAIRS, MOTORRESISTANCE); 40 | BLDCDriver3PWM driver2 = BLDCDriver3PWM(PA0, PA1, PA2, PC14); 41 | MagneticSensorPWM sensor2 = MagneticSensorPWM(SENSORPWM2, SENSORMINPULSE, SENSORMAXPULSE); 42 | 43 | char message[MESSAGESIZE]; 44 | float motorTargetCurrent = 0; 45 | float motorTargetVelocity = 0; 46 | float motorTargetVoltage = 0; 47 | 48 | void setup() 49 | { 50 | blink(2, 100); 51 | 52 | initI2C(); 53 | initMotors(); 54 | 55 | blink(3, 200); 56 | } 57 | 58 | void loop() 59 | { 60 | // main FOC algorithm function 61 | motor1.loopFOC(); 62 | motor2.loopFOC(); 63 | 64 | // Motion control function 65 | motor1.move(motorTargetVoltage); 66 | motor2.move(motorTargetVoltage); 67 | } 68 | 69 | void blink(int amount, int del) { 70 | pinMode(LEDPIN, OUTPUT); 71 | 72 | for (int i = 0; i < amount; i++) { 73 | digitalWrite(LEDPIN, HIGH); 74 | delay(del); 75 | digitalWrite(LEDPIN, LOW); 76 | delay(del); 77 | } 78 | } 79 | 80 | void initI2C() { 81 | Wire.setSDA(SDAPIN); 82 | Wire.setSCL(SCLPIN); 83 | Wire.begin(SLAVEADDRESS); 84 | Wire.onReceive(receiveFun); 85 | Wire.onRequest(requestFun); 86 | } 87 | 88 | void initMotors() { 89 | pinMode(SENSORPWM1, INPUT); 90 | pinMode(SENSORPWM2, INPUT); 91 | 92 | sensor1.init(); 93 | motor1.linkSensor(&sensor1); 94 | driver1.voltage_power_supply = SUPPLYVOLTAGE; 95 | driver1.voltage_limit = VOLTAGELIMITDRIVER; 96 | driver1.init(); 97 | motor1.linkDriver(&driver1); 98 | motor1.voltage_limit = VOLTAGELIMITMOTOR; 99 | motor1.voltage_sensor_align = VOLTAGELIMITMOTOR; 100 | motor1.torque_controller = TorqueControlType::voltage; 101 | motor1.controller = MotionControlType::torque; 102 | motor1.init(); 103 | motor1.initFOC(); 104 | 105 | sensor2.init(); 106 | motor2.linkSensor(&sensor2); 107 | driver2.voltage_power_supply = SUPPLYVOLTAGE; 108 | driver2.voltage_limit = VOLTAGELIMITDRIVER; 109 | driver2.init(); 110 | motor2.linkDriver(&driver2); 111 | motor2.voltage_limit = VOLTAGELIMITMOTOR; 112 | motor2.voltage_sensor_align = VOLTAGELIMITMOTOR; 113 | motor2.torque_controller = TorqueControlType::voltage; 114 | motor2.controller = MotionControlType::torque; 115 | motor2.init(); 116 | motor2.initFOC(); 117 | } 118 | 119 | void receiveFun (int bytes) 120 | { 121 | int i = 0; 122 | while (Wire.available() && i < MESSAGESIZE) 123 | { 124 | message[i] = Wire.read(); 125 | i++; 126 | } 127 | 128 | float spd = message[1]; 129 | float str = message[2]; 130 | 131 | //de-normalize values 132 | spd = spd - 128; 133 | spd = spd / 128 * MAXTARGETVOLTAGE; 134 | motorTargetVoltage = spd; 135 | } 136 | 137 | void requestFun() 138 | { 139 | // Convert from angular rad/s to linear velocity m/s 140 | // TODO calculate correct conversion factor 141 | float vel = sensor1.getVelocity() + sensor2.getVelocity() / 2 * WHEELRADIUS; 142 | // TODO check I2C float specs, convert if neccessary 143 | Wire.write(vel); 144 | } 145 | --------------------------------------------------------------------------------