Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed-dev-f303 FastPWM3
Revision 45:26801179208e, committed 2018-06-27
- Comitter:
- benkatz
- Date:
- Wed Jun 27 03:44:44 2018 +0000
- Parent:
- 44:8040fa2fcb0d
- Child:
- 46:2d4b1dafcfe3
- Commit message:
- Lots of changes, seems to have broken calibration
Changed in this revision
--- a/Calibration/calibration.cpp Mon Jun 11 00:04:06 2018 +0000
+++ b/Calibration/calibration.cpp Wed Jun 27 03:44:44 2018 +0000
@@ -16,7 +16,7 @@
printf("\n\r Checking phase ordering\n\r");
float theta_ref = 0;
float theta_actual = 0;
- float v_d = .15f; //Put all volts on the D-Axis
+ float v_d = .05f; //Put all volts on the D-Axis
float v_q = 0.0f;
float v_u, v_v, v_w = 0;
float dtc_u, dtc_v, dtc_w = .5f;
@@ -88,7 +88,7 @@
int raw_b[n] = {0};
float theta_ref = 0;
float theta_actual = 0;
- float v_d = .15f; // Put volts on the D-Axis
+ float v_d = .05f; // Put volts on the D-Axis
float v_q = 0.0f;
float v_u, v_v, v_w = 0;
float dtc_u, dtc_v, dtc_w = .5f;
--- a/Config/motor_config.h Mon Jun 11 00:04:06 2018 +0000 +++ b/Config/motor_config.h Wed Jun 27 03:44:44 2018 +0000 @@ -1,14 +1,14 @@ #ifndef MOTOR_CONFIG_H #define MOTOR_CONFIG_H -#define R_PHASE 0.105f //Ohms +#define R_PHASE 0.13f //Ohms #define L_D 0.00003f //Henries #define L_Q 0.00003f //Henries #define KT .075f //N-m per peak phase amp, = WB*NPP*3/2 #define NPP 21 //Number of pole pairs #define GR 6.0f //Gear ratio #define KT_OUT 0.45f //KT*GR -#define WB 0.0024f //Webers. +#define WB 0.0024f //Flux linkage, Webers.
--- a/DRV8323/DRV.cpp Mon Jun 11 00:04:06 2018 +0000
+++ b/DRV8323/DRV.cpp Wed Jun 27 03:44:44 2018 +0000
@@ -109,4 +109,10 @@
{
uint16_t val = (read_register(DCR)) | (0x1<<2);
write_register(DCR, val);
+ }
+
+void DRV832x::calibrate(void)
+{
+ uint16_t val = 0x1<<4 + 0x1<<3 + 0x1<<2;
+ write_register(CSACR, val);
}
\ No newline at end of file
--- a/DRV8323/DRV.h Mon Jun 11 00:04:06 2018 +0000
+++ b/DRV8323/DRV.h Wed Jun 27 03:44:44 2018 +0000
@@ -35,6 +35,7 @@
void write_CSACR(int CSA_FET, int VREF_DIV, int LS_REF, int CSA_GAIN, int DIS_SEN, int CSA_CAL_A, int CSA_CAL_B, int CSA_CAL_C, int SEN_LVL);
void enable_gd(void);
void disable_gd(void);
+ void calibrate(void);
void print_faults();
private:
--- a/FOC/foc.cpp Mon Jun 11 00:04:06 2018 +0000
+++ b/FOC/foc.cpp Wed Jun 27 03:44:44 2018 +0000
@@ -56,6 +56,15 @@
*offset_1 = adc1_offset/n;
*offset_2 = adc2_offset/n;
}
+
+void init_controller_params(ControllerStruct *controller){
+ controller->ki_d = KI_D;
+ controller->ki_q = KI_Q;
+ controller->k_d = K_SCALE*I_BW;
+ controller->k_q = K_SCALE*I_BW;
+ controller->alpha = 1.0f - 1.0f/(1.0f - DT*I_BW*2.0f*PI);
+
+ }
void reset_foc(ControllerStruct *controller){
TIM1->CCR3 = (PWM_ARR>>1)*(0.5f);
@@ -71,6 +80,12 @@
controller->v_q = 0;
controller->v_d = 0;
}
+
+void limit_current_ref (ControllerStruct *controller){
+ float i_q_max_limit = (0.5774f*controller->v_bus - controller->dtheta_elec*WB)/R_PHASE;
+ float i_q_min_limit = (-0.5774f*controller->v_bus - controller->dtheta_elec*WB)/R_PHASE;
+ controller->i_q_ref = fmaxf(fminf(i_q_max_limit, controller->i_q_ref), i_q_min_limit);
+ }
void commutate(ControllerStruct *controller, ObserverStruct *observer, GPIOStruct *gpio, float theta){
@@ -109,44 +124,45 @@
observer->i_q_est += K_O*observer->e_q + .001f*observer->e_q_int;
- float scog12 = FastSin(12.0f*theta);
- float scog1 = s;
- float cogging_current = 0.25f*scog1 - 0.3f*scog12;
+ //float scog12 = FastSin(12.0f*theta);
+ //float scog1 = s;
+ //float cogging_current = 0.25f*scog1 - 0.3f*scog12;
+
+ // Filter the current references to the desired closed-loopbandwidth
+ // Allows calculation of desired di/dt for inductance, etc
+ controller->did_dt = controller->i_d_ref_filt;
+ controller->diq_dt = controller->i_q_ref_filt;
+ controller->i_d_ref_filt = (1.0f-controller->alpha)*controller->i_d_ref_filt + controller->alpha*controller->i_d_ref;
+ controller->i_q_ref_filt = (1.0f-controller->alpha)*controller->i_q_ref_filt + controller->alpha*controller->i_q_ref;
+ controller->did_dt = (controller->i_d_ref_filt - controller->did_dt)/DT;
+ controller->diq_dt = (controller->i_q_ref_filt - controller->diq_dt)/DT;
/// PI Controller ///
float i_d_error = controller->i_d_ref - controller->i_d;
- float i_q_error = controller->i_q_ref - controller->i_q + cogging_current;
+ float i_q_error = controller->i_q_ref - controller->i_q;// + cogging_current;
- float v_d_ff = 2.0f*(controller->i_d_ref*R_PHASE - controller->dtheta_elec*L_Q*controller->i_q_ref); //feed-forward voltages
- float v_q_ff = 2.0f*(controller->i_q_ref*R_PHASE + controller->dtheta_elec*(L_D*controller->i_d_ref + WB));
+ // Calculate feed-forward voltages //
+ float v_d_ff = 2.0f*(controller->i_d_ref*R_PHASE + L_D*controller->did_dt - controller->dtheta_elec*L_Q*controller->i_q_ref); //feed-forward voltages
+ float v_q_ff = 2.0f*(controller->i_q_ref*R_PHASE + L_Q*controller->diq_dt + controller->dtheta_elec*(L_D*controller->i_d_ref + WB));
+ // Integrate Error //
controller->d_int += i_d_error;
controller->q_int += i_q_error;
-
- //v_d_ff = 0;
- //v_q_ff = 0;
-
- limit_norm(&controller->d_int, &controller->q_int, V_BUS/(K_SCALE*I_BW*KI_Q)); // Limit integrators to prevent windup
- controller->v_d = K_SCALE*I_BW*i_d_error + K_SCALE*I_BW*KI_D*controller->d_int;// + v_d_ff;
- controller->v_q = K_SCALE*I_BW*i_q_error + K_SCALE*I_BW*KI_Q*controller->q_int;// + v_q_ff;
-
- //controller->v_q = 4.0f;
- //controller->v_d = 0.0f;
-
- //controller->v_d = v_d_ff;
- //controller->v_q = v_q_ff;
+
+ limit_norm(&controller->d_int, &controller->q_int, V_BUS/(controller->k_q*controller->ki_q));
+ controller->v_d = controller->k_d*(i_d_error + controller->ki_d*controller->d_int);// + v_d_ff;
+ controller->v_q = controller->k_q*(i_q_error + controller->ki_q*controller->q_int);// + v_q_ff;
limit_norm(&controller->v_d, &controller->v_q, OVERMODULATION*controller->v_bus); // Normalize voltage vector to lie within curcle of radius v_bus
- abc(controller->theta_elec+0.5f*DT*controller->dtheta_elec, controller->v_d, controller->v_q, &controller->v_u, &controller->v_v, &controller->v_w); //inverse dq0 transform on voltages
-
- //controller->v_u = c*controller->v_d - s*controller->v_q; // Faster Inverse DQ0 transform
- //controller->v_v = (0.86602540378f*s-.5f*c)*controller->v_d - (-0.86602540378f*c-.5f*s)*controller->v_q;
- //controller->v_w = (-0.86602540378f*s-.5f*c)*controller->v_d - (0.86602540378f*c-.5f*s)*controller->v_q;
+ abc(controller->theta_elec, controller->v_d, controller->v_q, &controller->v_u, &controller->v_v, &controller->v_w); //inverse dq0 transform on voltages
svm(controller->v_bus, controller->v_u, controller->v_v, controller->v_w, &controller->dtc_u, &controller->dtc_v, &controller->dtc_w); //space vector modulation
observer->i_d_dot = 0.5f*(controller->v_d - 2.0f*(observer->i_d_est*R_PHASE - controller->dtheta_elec*L_Q*observer->i_q_est))/L_D; //feed-forward voltage
observer->i_q_dot = 0.5f*(controller->v_q - 2.0f*(observer->i_q_est*R_PHASE + controller->dtheta_elec*(L_D*observer->i_d_est + WB)))/L_Q;
+ //controller->dtc_u = 0.5f;
+ //controller->dtc_v = 0.6f;
+ //controller->dtc_w = 0.5f;
if(PHASE_ORDER){ // Check which phase order to use,
TIM1->CCR3 = (PWM_ARR)*(1.0f-controller->dtc_u); // Write duty cycles
TIM1->CCR2 = (PWM_ARR)*(1.0f-controller->dtc_v);
@@ -168,7 +184,7 @@
//printf("%.2f %.2f %.2f\n\r", controller->i_a, controller->i_b, controller->i_c);
//printf("%f\n\r", controller->dtheta_mech*GR);
//pc.printf("%f %f %f\n\r", controller->i_a, controller->i_b, controller->i_c);
- //pc.printf("%f %f\n\r", controller->i_d, controller->i_q);
+ //printf("%f %f\n\r", controller->k_d, controller->k_q);
//pc.printf("%d %d\n\r", controller->adc1_raw, controller->adc2_raw);
}
}
--- a/FOC/foc.h Mon Jun 11 00:04:06 2018 +0000 +++ b/FOC/foc.h Wed Jun 27 03:44:44 2018 +0000 @@ -17,6 +17,8 @@ void svm(float v_bus, float u, float v, float w, float *dtc_u, float *dtc_v, float *dtc_w); void zero_current(int *offset_1, int *offset_2); void reset_foc(ControllerStruct *controller); +void init_controller_params(ControllerStruct *controller); void commutate(ControllerStruct *controller, ObserverStruct *observer, GPIOStruct *gpio, float theta); void torque_control(ControllerStruct *controller); +void limit_current_ref (ControllerStruct *controller); #endif
--- a/PositionSensor/PositionSensor.cpp Mon Jun 11 00:04:06 2018 +0000
+++ b/PositionSensor/PositionSensor.cpp Wed Jun 27 03:44:44 2018 +0000
@@ -25,10 +25,8 @@
}
void PositionSensorAM5147::Sample(){
- GPIOA->ODR &= ~(1 << 15);
raw = spi->write(readAngleCmd);
raw &= 0x3FFF; //Extract last 14 bits
- GPIOA->ODR |= (1 << 15);
int off_1 = offset_lut[raw>>7];
int off_2 = offset_lut[((raw>>7)+1)%128];
int off_interp = off_1 + ((off_2 - off_1)*(raw - ((raw>>7)<<7))>>7); // Interpolate between lookup table entries
--- a/main.cpp Mon Jun 11 00:04:06 2018 +0000
+++ b/main.cpp Wed Jun 27 03:44:44 2018 +0000
@@ -1,5 +1,5 @@
/// high-bandwidth 3-phase motor control, for robots
-/// Written by benkatz, with much inspiration from bayleyw, nkirkby, scolton, David Otten, and others
+/// Written by benkatz, with much inspiration from Bayley Wang, Nick Kirkby, Shane Colton, David Otten, and others
/// Hardware documentation can be found at build-its.blogspot.com
/// Written for the STM32F446, but can be implemented on other STM32 MCU's with some further register-diddling
@@ -9,7 +9,7 @@
#define SETUP_MODE 4
#define ENCODER_MODE 5
-#define VERSION_NUM "1.6"
+#define VERSION_NUM "1.7"
float __float_reg[64]; // Floats stored in flash
@@ -41,7 +41,7 @@
Serial pc(PA_2, PA_3);
-CAN can(PB_8, PB_9); // CAN Rx pin name, CAN Tx pin name
+CAN can(PB_8, PB_9, 1000000); // CAN Rx pin name, CAN Tx pin name
CANMessage rxMsg;
CANMessage txMsg;
@@ -164,15 +164,16 @@
ADC1->CR2 |= 0x40000000; // Begin sample and conversion
//volatile int delay;
//for (delay = 0; delay < 55; delay++);
+
+ spi.Sample(); // sample position sensor
controller.adc2_raw = ADC2->DR; // Read ADC Data Registers
controller.adc1_raw = ADC1->DR;
controller.adc3_raw = ADC3->DR;
- spi.Sample(); // sample position sensor
controller.theta_elec = spi.GetElecPosition();
controller.theta_mech = (1.0f/GR)*spi.GetMechPosition();
controller.dtheta_mech = (1.0f/GR)*spi.GetMechVelocity();
controller.dtheta_elec = spi.GetElecVelocity();
- controller.v_bus = 0.95f*controller.v_bus + 0.05f*((float)controller.adc3_raw)*V_SCALE;
+ controller.v_bus = 24.0f;//0.95f*controller.v_bus + 0.05f*((float)controller.adc3_raw)*V_SCALE;
///
/// Check state machine state, and run the appropriate function ///
@@ -213,20 +214,22 @@
controller.kd = 0;
controller.t_ff = 0;
}
- //commutate(&controller, &observer, &gpio, controller.theta_elec); // Run current loop
- TIM1->CCR3 = (PWM_ARR)*(0.5f); // Write duty cycles
- TIM1->CCR2 = (PWM_ARR)*(0.5f);
- TIM1->CCR1 = (PWM_ARR)*(0.5f);
+ controller.i_q_ref = 2.0f;
+ commutate(&controller, &observer, &gpio, controller.theta_elec); // Run current loop
+ //TIM1->CCR3 = (PWM_ARR)*(0.5f); // Write duty cycles
+ //TIM1->CCR2 = (PWM_ARR)*(0.5f);
+ //TIM1->CCR1 = (PWM_ARR)*(0.5f);
controller.timeout += 1;
/*
count++;
if(count == 4000){
- //printf("%.4f\n\r", controller.dtheta_mech);
-
+ printf("%d %d %.4f %.4f %.4f\n\r", controller.adc1_raw, controller.adc2_raw, controller.i_a, controller.i_b, controller.i_c);
+ //printf("%.3f\n\r", controller.dtheta_mech);
count = 0;
}
- */
+ */
+
}
@@ -351,7 +354,6 @@
}
int main() {
- can.frequency(1000000); // set bit rate to 1Mbps
controller.v_bus = V_BUS;
controller.mode = 0;
Init_All_HW(&gpio); // Setup PWM, ADC, GPIO
@@ -359,12 +361,17 @@
gpio.enable->write(1);
wait_us(100);
+ drv.calibrate();
+ wait_us(100);
drv.write_DCR(0x0, 0x0, 0x0, PWM_MODE_3X, 0x0, 0x0, 0x0, 0x0, 0x1);
wait_us(100);
drv.write_CSACR(0x0, 0x1, 0x0, CSA_GAIN_40, 0x0, 0x0, 0x0, 0x0, 0x3);
wait_us(100);
+
+ //drv.enable_gd();
zero_current(&controller.adc1_offset, &controller.adc2_offset); // Measure current sensor zero-offset
+ //drv.disable_gd();
@@ -377,7 +384,6 @@
TIM1->CCR1 = 0x708*(1.0f);
gpio.enable->write(0);
*/
-
reset_foc(&controller); // Reset current controller
TIM1->CR1 ^= TIM_CR1_UDIS;
//TIM1->CR1 |= TIM_CR1_UDIS; //enable interrupt
@@ -401,7 +407,8 @@
int lut[128] = {0};
memcpy(&lut, &ENCODER_LUT, sizeof(lut));
spi.WriteLUT(lut); // Set potision sensor nonlinearity lookup table
-
+ init_controller_params(&controller);
+
pc.baud(921600); // set serial baud rate
wait(.01);
pc.printf("\n\r\n\r HobbyKing Cheetah\n\r\n\r");
@@ -429,19 +436,5 @@
int counter = 0;
while(1) {
-counter++;
- if(counter>40000)
- {
- //gpio.enable->write(1);
- //wait_us(100);
- //printf(" %d\n\r", drv.read_register(DCR));
- //wait_us(100);
- //printf(" %d\n\r", drv.read_register(CSACR));
- drv.print_faults();
- //printf("%d\n\r", drv.read_register(DCR));
- counter = 0;
- //gpio.enable->write(0);
- }
- wait_us(25);
}
}
--- a/structs.h Mon Jun 11 00:04:06 2018 +0000
+++ b/structs.h Wed Jun 27 03:44:44 2018 +0000
@@ -17,23 +17,25 @@
}COMStruct;
typedef struct{
- int adc1_raw, adc2_raw, adc3_raw;
- float i_a, i_b, i_c;
- float v_bus;
- float theta_mech, theta_elec;
- float dtheta_mech, dtheta_elec, dtheta_elec_filt;
- float i_d, i_q, i_q_filt;
- float v_d, v_q;
- float dtc_u, dtc_v, dtc_w;
- float v_u, v_v, v_w;
- float d_int, q_int;
- int adc1_offset, adc2_offset;
- float i_d_ref, i_q_ref;
- int loop_count;
- int timeout;
+ int adc1_raw, adc2_raw, adc3_raw; // Raw ADC Values
+ float i_a, i_b, i_c; // Phase currents
+ float v_bus; // DC link voltage
+ float theta_mech, theta_elec; // Rotor mechanical and electrical angle
+ float dtheta_mech, dtheta_elec, dtheta_elec_filt; // Rotor mechanical and electrical angular velocit
+ float i_d, i_q, i_q_filt; // D/Q currents
+ float v_d, v_q; // D/Q voltages
+ float dtc_u, dtc_v, dtc_w; // Terminal duty cycles
+ float v_u, v_v, v_w; // Terminal voltages
+ float k_d, k_q, ki_d, ki_q, alpha; // Current loop gains, current reference filter coefficient
+ float d_int, q_int; // Current error integrals
+ int adc1_offset, adc2_offset; // ADC offsets
+ float i_d_ref, i_q_ref, i_d_ref_filt, i_q_ref_filt; // Current references
+ float did_dt, diq_dt; // Current reference derivatives
+ int loop_count; // Degubbing counter
+ int timeout; // Watchdog counter
int mode;
- int ovp_flag;
- float p_des, v_des, kp, kd, t_ff;
+ int ovp_flag; // Over-voltage flag
+ float p_des, v_des, kp, kd, t_ff; // Desired position, velocity, gians, torque
float cogging[128];
} ControllerStruct;