Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional SVM variations #590

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions confgenerator.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ int32_t confgenerator_serialize_mcconf(uint8_t *buffer, const mc_configuration *
buffer_append_float16(buffer, conf->foc_fw_ramp_time, 1000, &ind);
buffer_append_float16(buffer, conf->foc_fw_q_current_factor, 10000, &ind);
buffer[ind++] = conf->foc_speed_soure;
buffer[ind++] = conf->foc_commutation_type;
buffer_append_int16(buffer, conf->gpd_buffer_notify_left, &ind);
buffer_append_int16(buffer, conf->gpd_buffer_interpol, &ind);
buffer_append_float16(buffer, conf->gpd_current_filter_const, 10000, &ind);
Expand Down Expand Up @@ -532,6 +533,7 @@ bool confgenerator_deserialize_mcconf(const uint8_t *buffer, mc_configuration *c
conf->foc_fw_ramp_time = buffer_get_float16(buffer, 1000, &ind);
conf->foc_fw_q_current_factor = buffer_get_float16(buffer, 10000, &ind);
conf->foc_speed_soure = buffer[ind++];
conf->foc_commutation_type = buffer[ind++];
conf->gpd_buffer_notify_left = buffer_get_int16(buffer, &ind);
conf->gpd_buffer_interpol = buffer_get_int16(buffer, &ind);
conf->gpd_current_filter_const = buffer_get_float16(buffer, 10000, &ind);
Expand Down Expand Up @@ -925,6 +927,7 @@ void confgenerator_set_defaults_mcconf(mc_configuration *conf) {
conf->foc_fw_ramp_time = MCCONF_FOC_FW_RAMP_TIME;
conf->foc_fw_q_current_factor = MCCONF_FOC_FW_Q_CURRENT_FACTOR;
conf->foc_speed_soure = MCCONF_FOC_SPEED_SOURCE;
conf->foc_commutation_type = MCCONF_FOC_COMMUTATION_TYPE;
conf->gpd_buffer_notify_left = MCCONF_GPD_BUFFER_NOTIFY_LEFT;
conf->gpd_buffer_interpol = MCCONF_GPD_BUFFER_INTERPOL;
conf->gpd_current_filter_const = MCCONF_GPD_CURRENT_FILTER_CONST;
Expand Down
2 changes: 1 addition & 1 deletion confgenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <stdbool.h>

// Constants
#define MCCONF_SIGNATURE 776184161
#define MCCONF_SIGNATURE 608083588
#define APPCONF_SIGNATURE 486554156

// Functions
Expand Down
9 changes: 9 additions & 0 deletions datatypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@
#include "ch.h"

// Data types
typedef enum {
ALT_REV_SEQ = 0, // alternating reversing sequence (previous implementation)
NULL_V0, // flat bottom
NULL_V7, // flat top
V7_ODD_V0_EVEN, // v7 in [1,3,5] v0 in [2,4,6]
V0_ODD_V7_EVEN, // v0 in [1,3,5] v7 in [2,4,6]
} commutation_technique_t;

typedef enum {
HW_TYPE_VESC = 0,
HW_TYPE_VESC_BMS,
Expand Down Expand Up @@ -458,6 +466,7 @@ typedef struct {
bool foc_phase_filter_disable_fault;
float foc_phase_filter_max_erpm;
MTPA_MODE foc_mtpa_mode;
commutation_technique_t foc_commutation_type;
// Field Weakening
float foc_fw_current_max;
float foc_fw_duty_start;
Expand Down
281 changes: 181 additions & 100 deletions motor/foc_math.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include "utils_math.h"
#include <math.h>


const uint8_t sector_LUT[6] = {6u, 2u, 1u, 4u, 5u, 3u};


// See http://cas.ensmp.fr/~praly/Telechargement/Journaux/2010-IEEE_TPEL-Lee-Hong-Nam-Ortega-Praly-Astolfi.pdf
void foc_observer_update(float v_alpha, float v_beta, float i_alpha, float i_beta,
float dt, observer_state *state, float *phase, motor_all_state_t *motor) {
Expand Down Expand Up @@ -196,137 +200,214 @@ void foc_pll_run(float phase, float dt, float *phase_var,
/**
* @brief svm Space vector modulation. Magnitude must not be larger than sqrt(3)/2, or 0.866 to avoid overmodulation.
* See https://github.com/vedderb/bldc/pull/372#issuecomment-962499623 for a full description.
* See the follwoing links for a full description:
* https://youtu.be/5eQyoVMz1dY
* https://link.gale.com/apps/doc/A18320578/AONE
* @param alpha voltage
* @param beta Park transformed and normalized voltage
* @param PWMFullDutyCycle is the peak value of the PWM counter.
* @param tAout PWM duty cycle phase A (0 = off all of the time, PWMFullDutyCycle = on all of the time)
* @param tBout PWM duty cycle phase B
* @param tCout PWM duty cycle phase C
* @param tBout PWM duty cycle phase B (0 = off all of the time, PWMFullDutyCycle = on all of the time)
* @param tCout PWM duty cycle phase C (0 = off all of the time, PWMFullDutyCycle = on all of the time)
*/
void foc_svm(float alpha, float beta, uint32_t PWMFullDutyCycle,
uint32_t* tAout, uint32_t* tBout, uint32_t* tCout, uint32_t *svm_sector) {
uint32_t sector;

if (beta >= 0.0f) {
if (alpha >= 0.0f) {
//quadrant I
if (ONE_BY_SQRT3 * beta > alpha) {
sector = 2;
} else {
sector = 1;
}
} else {
//quadrant II
if (-ONE_BY_SQRT3 * beta > alpha) {
sector = 3;
} else {
sector = 2;
}
}
} else {
if (alpha >= 0.0f) {
//quadrant IV5
if (-ONE_BY_SQRT3 * beta > alpha) {
sector = 5;
} else {
sector = 6;
}
} else {
//quadrant III
if (ONE_BY_SQRT3 * beta > alpha) {
sector = 4;
} else {
sector = 5;
}
}
}
uint32_t* tAout, uint32_t* tBout, uint32_t* tCout,
uint32_t *svm_sector, commutation_technique_t comm_tech) {

// PWM timings
uint32_t tA, tB, tC;
uint32_t tA = 0u, tB = 0u, tC = 0u, N = 0u, sector = 0u;
float T0 = 0.0f, T1 = 0.0f, T2 = 0.0f, a = 0.0f, b = 0.0f, c = 0.0f, temp = 0.0f;

switch (sector) {
a = SQRT3_BY_2*alpha - 0.5f*beta;
b = beta;

// sector 1-2
case 1: {
// Vector on-times
uint32_t t1 = (alpha - ONE_BY_SQRT3 * beta) * PWMFullDutyCycle;
uint32_t t2 = (TWO_BY_SQRT3 * beta) * PWMFullDutyCycle;
temp = (float)PWMFullDutyCycle/SQRT3_BY_2;

// PWM timings
tA = (PWMFullDutyCycle + t1 + t2) / 2;
tB = tA - t1;
tC = tB - t2;
a *= temp;
b *= temp;
c = -1.0f*(a+b); // kirchhoff current law (current in = current out)

N = (((int32_t)a) >= 0) + 2u*(((int32_t)b) >= 0) + 4u*(((int32_t)c) >= 0);
N = (N > 6u || N == 0u) ? 2u : N-1; // if a, b, c are all zero (happens when alpha & beta are zero) or negative set it to index 2 (sector 1)
sector = sector_LUT[N];

switch(sector) {
case 1: {
T1 = a;
T2 = b;
T0 = (float)PWMFullDutyCycle - T1 - T2;

switch (comm_tech) {
case ALT_REV_SEQ:
default:
tA = (uint32_t)(T1+T2+0.5f*T0);
tB = (uint32_t)(T2+0.5f*T0);
tC = (uint32_t)(0.5f*T0);
break;

case V0_ODD_V7_EVEN:
case NULL_V0:
tA = (uint32_t)(T1+T2);
tB = (uint32_t)(T2);
tC = (uint32_t)(0);
break;

case V7_ODD_V0_EVEN:
case NULL_V7:
tA = (uint32_t)(PWMFullDutyCycle);
tB = (uint32_t)(T0+T2);
tC = (uint32_t)(T0);
break;
}
break;
}

// sector 2-3
case 2: {
// Vector on-times
uint32_t t2 = (alpha + ONE_BY_SQRT3 * beta) * PWMFullDutyCycle;
uint32_t t3 = (-alpha + ONE_BY_SQRT3 * beta) * PWMFullDutyCycle;

// PWM timings
tB = (PWMFullDutyCycle + t2 + t3) / 2;
tA = tB - t3;
tC = tA - t2;

T1 = -c;
T2 = -a;
T0 = (float)PWMFullDutyCycle - T1 - T2;

switch (comm_tech) {
case ALT_REV_SEQ:
default:
tA = (uint32_t)(T1+0.5f*T0);
tB = (uint32_t)(T1+T2+0.5f*T0);
tC = (uint32_t)(0.5f*T0);
break;

case V7_ODD_V0_EVEN:
case NULL_V0:
tA = (uint32_t)(T1);
tB = (uint32_t)(T1+T2);
tC = (uint32_t)(0);
break;

case V0_ODD_V7_EVEN:
case NULL_V7:
tA = (uint32_t)(T0+T1);
tB = (uint32_t)(PWMFullDutyCycle);
tC = (uint32_t)(T0);
break;
}
break;
}

// sector 3-4
case 3: {
// Vector on-times
uint32_t t3 = (TWO_BY_SQRT3 * beta) * PWMFullDutyCycle;
uint32_t t4 = (-alpha - ONE_BY_SQRT3 * beta) * PWMFullDutyCycle;

// PWM timings
tB = (PWMFullDutyCycle + t3 + t4) / 2;
tC = tB - t3;
tA = tC - t4;

T1 = b;
T2 = c;
T0 = (float)PWMFullDutyCycle - T1 - T2;

switch (comm_tech) {
case ALT_REV_SEQ:
default:
tA = (uint32_t)(0.5f*T0);
tB = (uint32_t)(T1+T2+0.5f*T0);
tC = (uint32_t)(T2+0.5f*T0);
break;

case V0_ODD_V7_EVEN:
case NULL_V0:
tA = (uint32_t)(0);
tB = (uint32_t)(T1+T2);
tC = (uint32_t)(T2);
break;

case V7_ODD_V0_EVEN:
case NULL_V7:
tA = (uint32_t)(T0);
tB = (uint32_t)(PWMFullDutyCycle);
tC = (uint32_t)(T0+T2);
break;
}
break;
}

// sector 4-5
case 4: {
// Vector on-times
uint32_t t4 = (-alpha + ONE_BY_SQRT3 * beta) * PWMFullDutyCycle;
uint32_t t5 = (-TWO_BY_SQRT3 * beta) * PWMFullDutyCycle;

// PWM timings
tC = (PWMFullDutyCycle + t4 + t5) / 2;
tB = tC - t5;
tA = tB - t4;

T1 = -a;
T2 = -b;
T0 = (float)PWMFullDutyCycle - T1 - T2;

switch (comm_tech) {
case ALT_REV_SEQ:
default:
tA = (uint32_t)(0.5f*T0);
tB = (uint32_t)(T1+0.5f*T0);
tC = (uint32_t)(T1+T2+0.5f*T0);
break;

case V7_ODD_V0_EVEN:
case NULL_V0:
tA = (uint32_t)(0);
tB = (uint32_t)(T1);
tC = (uint32_t)(T1+T2);
break;

case V0_ODD_V7_EVEN:
case NULL_V7:
tA = (uint32_t)(T0);
tB = (uint32_t)(T0+T1);
tC = (uint32_t)(PWMFullDutyCycle);
break;
}
break;
}

// sector 5-6
case 5: {
// Vector on-times
uint32_t t5 = (-alpha - ONE_BY_SQRT3 * beta) * PWMFullDutyCycle;
uint32_t t6 = (alpha - ONE_BY_SQRT3 * beta) * PWMFullDutyCycle;

// PWM timings
tC = (PWMFullDutyCycle + t5 + t6) / 2;
tA = tC - t5;
tB = tA - t6;

T1 = c;
T2 = a;
T0 = (float)PWMFullDutyCycle - T1 - T2;

switch (comm_tech) {
case ALT_REV_SEQ:
default:
tA = (uint32_t)(T2+0.5f*T0);
tB = (uint32_t)(0.5f*T0);
tC = (uint32_t)(T1+T2+0.5f*T0);
break;

case V0_ODD_V7_EVEN:
case NULL_V0:
tA = (uint32_t)(T2);
tB = (uint32_t)(0);
tC = (uint32_t)(T1+T2);
break;

case V7_ODD_V0_EVEN:
case NULL_V7:
tA = (uint32_t)(T0+T2);
tB = (uint32_t)(T0);
tC = (uint32_t)(PWMFullDutyCycle);
break;
}
break;
}

// sector 6-1
case 6: {
// Vector on-times
uint32_t t6 = (-TWO_BY_SQRT3 * beta) * PWMFullDutyCycle;
uint32_t t1 = (alpha + ONE_BY_SQRT3 * beta) * PWMFullDutyCycle;

// PWM timings
tA = (PWMFullDutyCycle + t6 + t1) / 2;
tC = tA - t1;
tB = tC - t6;

T1 = -b;
T2 = -c;
T0 = (float)PWMFullDutyCycle - T1 - T2;

switch (comm_tech) {
case ALT_REV_SEQ:
default:
tA = (uint32_t)(T1+T2+0.5f*T0);
tB = (uint32_t)(0.5f*T0);
tC = (uint32_t)(T1+0.5f*T0);
break;

case V7_ODD_V0_EVEN:
case NULL_V0:
tA = (uint32_t)(T1+T2);
tB = (uint32_t)(0);
tC = (uint32_t)(T1);
break;

case V0_ODD_V7_EVEN:
case NULL_V7:
tA = (uint32_t)(PWMFullDutyCycle);
tB = (uint32_t)(T0);
tC = (uint32_t)(T0+T1);
break;
}
break;
}
}
Expand Down
3 changes: 2 additions & 1 deletion motor/foc_math.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ void foc_observer_update(float v_alpha, float v_beta, float i_alpha, float i_bet
void foc_pll_run(float phase, float dt, float *phase_var,
float *speed_var, mc_configuration *conf);
void foc_svm(float alpha, float beta, uint32_t PWMFullDutyCycle,
uint32_t* tAout, uint32_t* tBout, uint32_t* tCout, uint32_t *svm_sector);
uint32_t* tAout, uint32_t* tBout, uint32_t* tCout,
uint32_t *svm_sector, commutation_technique_t comm_tech);
void foc_run_pid_control_pos(bool index_found, float dt, motor_all_state_t *motor);
void foc_run_pid_control_speed(float dt, motor_all_state_t *motor);
float foc_correct_encoder(float obs_angle, float enc_angle, float speed, float sl_erpm, motor_all_state_t *motor);
Expand Down
Loading