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

Calibration Fixes #293

Merged
merged 23 commits into from
Sep 21, 2023
Merged
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: 1 addition & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@
"test_*.py"
],
"python.testing.pytestEnabled": false,
"python.testing.unittestEnabled": true,
"python.formatting.provider": "black"
"python.testing.unittestEnabled": true
}
11 changes: 9 additions & 2 deletions firmware/src/adc/adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ static ADCState adc_state = {0};
static ADCConfig adc_config = {
.I_phase_offset = {0},
.Iphase_limit = 60.0f,
.I_phase_offset_tau = 0.5f,
.I_phase_offset_tau = 0.1f,
.temp_tau = 1.0
};

void ADC_Init(void)
void ADC_init(void)
{
// Compute tau-dependent variables
adc_state.I_phase_offset_D = 1.0f - powf(EPSILON, -1.0f / (adc_config.I_phase_offset_tau * PWM_FREQ_HZ));
Expand Down Expand Up @@ -183,6 +183,13 @@ void ADC_AIO_Init(void)
pac5xxx_tile_register_write(ADDR_CFGAIO5, HP_DIS_LP_EN_PR1 | OFFSET_EN | CAL_OFFSET_DIS | LP_HP_EN_1us);
}

void ADC_reset(void)
{
adc_config.I_phase_offset.A = 0;
adc_config.I_phase_offset.B = 0;
adc_config.I_phase_offset.C = 0;
}

void ADC_DTSE_Init(void)
{
//========================================================================================================
Expand Down
3 changes: 2 additions & 1 deletion firmware/src/adc/adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ typedef struct
float temp_tau;
} ADCConfig;

void ADC_Init(void);
void ADC_init(void);
void ADC_reset(void);
float adc_get_mcu_temp(void);
void ADC_GetPhaseCurrents(FloatTriplet *phc);
void ADC_update(void);
Expand Down
6 changes: 3 additions & 3 deletions firmware/src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@

#define ERROR_FLAG_MAX_SIZE (5u)

#define ENCODER_TICKS (8192)
#define ENCODER_TICKS_FLOAT (8192.f)
#define ENCODER_BITS (13)
#define ENCODER_TICKS (1 << ENCODER_BITS)
#define ENCODER_TICKS_FLOAT ((float)(ENCODER_TICKS))

#define HALL_SECTORS (6)
#define HALL_SECTOR_ANGLE (TWOPI / HALL_SECTORS)
Expand Down Expand Up @@ -134,7 +135,6 @@ static const float threehalfpi = 4.7123889f;
static const float pi = PI;
static const float halfpi = PI * 0.5f;
static const float quarterpi = PI * 0.25f;
//static const int32_t timer_freq_hz = ACLK_FREQ_HZ / (pow(2, TXCTL_PS_DIV)); // (alternative)
static const int32_t timer_freq_hz = ACLK_FREQ_HZ >> TXCTL_PS_DIV;
static const float twopi_by_enc_ticks = TWOPI / ENCODER_TICKS;
static const float twopi_by_hall_sectors = TWOPI / HALL_SECTORS;
Expand Down
2 changes: 1 addition & 1 deletion firmware/src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

// Encoder rectification lookup table size
#define ECN_BITS (6)
#define ECN_SIZE (2 << ECN_BITS)
#define ECN_SIZE (1 << ECN_BITS)

// UART
#define UART_ENUM UARTB
Expand Down
5 changes: 5 additions & 0 deletions firmware/src/encoder/hall.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ TM_RAMFUNC uint8_t hall_get_errors(void)
return state.errors;
}

TM_RAMFUNC uint8_t *hall_get_error_ptr(void)
{
return &(state.errors);
}

TM_RAMFUNC int16_t hall_get_angle(void)
{
return state.angle;
Expand Down
2 changes: 2 additions & 0 deletions firmware/src/encoder/hall.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ typedef struct
void hall_init(void);

uint8_t hall_get_errors(void);
uint8_t *hall_get_error_ptr(void);

int16_t hall_get_angle(void);
void hall_update(bool check_error);
uint8_t hall_get_sector(void);
Expand Down
7 changes: 4 additions & 3 deletions firmware/src/encoder/ma7xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@ TM_RAMFUNC int16_t ma7xx_get_angle_raw(void)

TM_RAMFUNC int16_t ma7xx_get_angle_rectified(void)
{
const uint8_t offset_bits = (ENCODER_BITS - ECN_BITS);
const int16_t angle = state.angle;
const int16_t off_1 = config.rec_table[angle>>ECN_BITS];
const int16_t off_2 = config.rec_table[((angle>>ECN_BITS) + 1) % ECN_SIZE];
const int16_t off_interp = off_1 + ((off_2 - off_1)* (angle - ((angle>>ECN_BITS)<<ECN_BITS))>>ECN_BITS);
const int16_t off_1 = config.rec_table[angle>>offset_bits];
const int16_t off_2 = config.rec_table[((angle>>offset_bits) + 1) % ECN_SIZE];
const int16_t off_interp = off_1 + ((off_2 - off_1)* (angle - ((angle>>offset_bits)<<offset_bits))>>offset_bits);
return angle + off_interp;
}

Expand Down
2 changes: 1 addition & 1 deletion firmware/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ int main(void)
encoder_init();
UART_Init();
observer_init();
ADC_Init();
ADC_init();
CAN_init();
Timer_Init();
Watchdog_init();
Expand Down
69 changes: 33 additions & 36 deletions firmware/src/motor/calibration.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,30 @@
#include <src/system/system.h>
#include <src/motor/calibration.h>

static inline void set_epos_and_wait(float angle, float I_setpoint);
static inline void wait_a_while(void);
static inline void set_epos_and_wait(float angle, float I_setpoint)
{
FloatTriplet modulation_values = {0.0f};
float pwm_setpoint = (I_setpoint * motor_get_phase_resistance()) / system_get_Vbus();
our_clampc(&pwm_setpoint, -PWM_LIMIT, PWM_LIMIT);
SVM(pwm_setpoint * fast_cos(angle), pwm_setpoint * fast_sin(angle),
&modulation_values.A, &modulation_values.B, &modulation_values.C);
gate_driver_set_duty_cycle(&modulation_values);
WaitForControlLoopInterrupt();
}

static inline void wait_pwm_cycles(uint32_t cycles)
{
for (uint32_t i = 0; i < cycles; i++)
{
WaitForControlLoopInterrupt();
}
}

bool CalibrateADCOffset(void)
{
// We only need to wait here, the ADC loop will
// perform the offset calibration automatically
wait_a_while();
wait_pwm_cycles(10000);
return true;
}

Expand Down Expand Up @@ -230,7 +246,7 @@ bool calibrate_hall_sequence(void)
}
else
{
uint8_t *error_ptr = motor_get_error_ptr();
uint8_t *error_ptr = hall_get_error_ptr();
*error_ptr |= ENCODER_ERRORS_CALIBRATION_FAILED;
}
return success;
Expand All @@ -239,19 +255,19 @@ bool calibrate_hall_sequence(void)
bool calibrate_offset_and_rectification(void)
{
// Size below is an arbitrary large number ie > ECN_SIZE * npp
int16_t error_ticks[ECN_SIZE * 24];
float error_ticks[ECN_SIZE * 20];
const int16_t npp = motor_get_pole_pairs();
const int16_t n = ECN_SIZE * npp;
const int16_t nconv = 50;
const int16_t nconv = 100;
const float delta = 2 * PI * npp / (n * nconv);
const float e_pos_to_ticks = ((float)ENCODER_TICKS) / (2 * PI * npp);
float e_pos_ref = 0.f;
const float I_setpoint = motor_get_I_cal();
ma7xx_clear_rec_table();
int16_t *lut = ma7xx_get_rec_table_ptr();
wait_a_while();
int16_t offset_raw = ma7xx_get_angle_raw();
// Perform measuerments, store only mean of F + B error
set_epos_and_wait(e_pos_ref, I_setpoint);
wait_pwm_cycles(5000);
const uint16_t offset_idx = ma7xx_get_angle_raw() >> (ENCODER_BITS - ECN_BITS);

for (uint32_t i = 0; i < n; i++)
{
for (uint8_t j = 0; j < nconv; j++)
Expand All @@ -263,7 +279,6 @@ bool calibrate_offset_and_rectification(void)
const float pos_meas = observer_get_pos_estimate();
error_ticks[i] = (int16_t)(e_pos_ref * e_pos_to_ticks - pos_meas);
}
offset_raw = (offset_raw + ma7xx_get_angle_raw()) / 2;
for (uint32_t i = 0; i < n; i++)
{
for (uint8_t j = 0; j < nconv; j++)
Expand All @@ -273,15 +288,15 @@ bool calibrate_offset_and_rectification(void)
}
WaitForControlLoopInterrupt();
const float pos_meas = observer_get_pos_estimate();
error_ticks[n - i - 1] = (int16_t)(0.5f * ((float)error_ticks[n - i - 1] + e_pos_ref * e_pos_to_ticks - pos_meas));
error_ticks[n - i - 1] += (int16_t)(e_pos_ref * e_pos_to_ticks - pos_meas);
}
gate_driver_set_duty_cycle(&three_phase_zero);
gate_driver_disable();

// FIR filtering and map measurements to lut
for (int16_t i=0; i<ECN_SIZE; i++)
{
int32_t acc = 0;
float acc = 0;
for (int16_t j = 0; j < ECN_SIZE; j++)
{
int16_t read_idx = -ECN_SIZE / 2 + j + i * npp;
Expand All @@ -295,44 +310,26 @@ bool calibrate_offset_and_rectification(void)
}
acc += error_ticks[read_idx];
}
acc /= ECN_SIZE;
int16_t write_idx = i + (offset_raw >> ECN_BITS);
acc = acc / ((float)(ECN_SIZE * 2));
int16_t write_idx = i + offset_idx;
if (write_idx > (ECN_SIZE - 1))
{
write_idx -= ECN_SIZE;
}
lut[write_idx] = (int16_t)acc;
}
wait_a_while();
wait_pwm_cycles(5000);
ma7xx_set_rec_calibrated();
return true;
}

void reset_calibration(void)
{
ADC_reset();
encoder_reset();
observer_reset();
motor_reset_calibration();
wait_a_while();
wait_pwm_cycles(5000);
}

static inline void set_epos_and_wait(float angle, float I_setpoint)
{
FloatTriplet modulation_values = {0.0f};
float pwm_setpoint = (I_setpoint * motor_get_phase_resistance()) / system_get_Vbus();
our_clampc(&pwm_setpoint, -PWM_LIMIT, PWM_LIMIT);
SVM(pwm_setpoint * fast_cos(angle), pwm_setpoint * fast_sin(angle),
&modulation_values.A, &modulation_values.B, &modulation_values.C);
gate_driver_set_duty_cycle(&modulation_values);
WaitForControlLoopInterrupt();
}

static inline void wait_a_while(void)
{
// Wait a while for the observer to settle
// TODO: This is a bit of a hack, can be improved!
for (int i = 0; i < 5000; i++)
{
WaitForControlLoopInterrupt();
}
}
2 changes: 1 addition & 1 deletion firmware/src/observer/observer.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
static ObserverState state = {0};

static ObserverConfig config = {
.track_bw = 300.0f,
.track_bw = 350.0f,
.kp = 0.0f,
.ki = 0.0f,
};
Expand Down
25 changes: 13 additions & 12 deletions firmware/src/system/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,19 @@ TM_RAMFUNC void system_update(void)
{
state.errors |= ERRORS_UNDERVOLTAGE;
}
const uint8_t drv_status = pac5xxx_tile_register_read(ADDR_STATDRV);
if (drv_status > 0)
{
state.errors |= ((drv_status & 0x7) << 4);
}
const uint8_t drv_fault = pac5xxx_tile_register_read(ADDR_DRV_FLT);
if (drv_fault > 0)
{
// We use 0x5 mask because we ignore CHARGE_PUMP_FAULT_STAT
// for the time being, as it seems to always be set.
state.errors |= ((drv_fault & 0x5) << 1);
}
// const uint8_t drv_status = pac5xxx_tile_register_read(ADDR_STATDRV);
// if (drv_status > 0)
// {
// state.errors |= ((drv_status & 0x56) << 1);
// }
// const uint8_t drv_fault = pac5xxx_tile_register_read(ADDR_DRV_FLT);
// if (drv_fault > 0)
// {
// // We use 0x5 mask because we ignore CHARGE_PUMP_FAULT_STAT
// // for the time being, as it seems to always be set, and
// // ERRORS_DRVXX_DISABLE, as it seems to give spurious errors.
// state.errors |= ((drv_fault & 0x5) << 1);
// }
}

void system_reset(void)
Expand Down
2 changes: 1 addition & 1 deletion firmware/src/utils/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

#if __ARM_FEATURE_FMA && __ARM_FP&4 && !__SOFTFP__ && !BROKEN_VFP_ASM

PAC5XXX_RAMFUNC static inline float fast_sqrt(float x)
static inline float fast_sqrt(float x)
{
__asm__ ("vsqrt.f32 %0, %1" : "=t"(x) : "t"(x));
return x;
Expand Down
5 changes: 2 additions & 3 deletions studio/Python/tests/test_board.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
A = ureg.ampere
ticks = ureg.ticks
s = ureg.second
tsleep = 0.18
tsleep = 0.19


class TestBoard(TMTestCase):
Expand Down Expand Up @@ -94,7 +94,6 @@ def test_d_position_control(self):
self.assertAlmostEqual(
i * 1000 * ticks, self.tm.encoder.position_estimate, delta=1000 * ticks
)
time.sleep(tsleep)

def test_e_velocity_control(self):
"""
Expand All @@ -105,7 +104,7 @@ def test_e_velocity_control(self):
self.tm.controller.velocity_mode()
self.check_state(2)

R = 14
R = 15

velocity_pairs = []

Expand Down