From 639b562d2bb4b8880d34f0f90c7e173c8f947f77 Mon Sep 17 00:00:00 2001 From: Nicolas Trimborn Date: Thu, 5 Aug 2021 18:53:54 +0200 Subject: [PATCH] commit poritng efforts --- .../.atmelstart/atmel_start_config.atstart | 4 +- .../Motor_Master/EtherCAT_SlaveDef.h | 69 ++-- .../Motor_Master/Motor_Master.cproj | 24 +- .../Motor_Master/Motor_Master/bldc.c | 338 ++++++++++++++++++ .../Motor_Master/Motor_Master/bldc.h | 142 +++++--- .../Motor_Master/Motor_Master/bldc_types.h | 109 ++++++ .../Motor_Master/Motor_Master/configuration.h | 57 +-- .../Motor_Master/Motor_Master/control.h | 256 +++++++++++++ .../Motor_Master/Motor_Master/interrupts.h | 1 + .../Motor_Master/Motor_Master/main.c | 86 ++++- .../Motor_Master/motorparameters.h | 149 +++++--- .../Motor_Master/Motor_Master/statemachine.h | 50 +++ .../Motor_Master/Motor_Master/utilities.h | 155 ++++++++ 13 files changed, 1275 insertions(+), 165 deletions(-) create mode 100644 2_Motor_Master/Motor_Master/Motor_Master/bldc_types.h create mode 100644 2_Motor_Master/Motor_Master/Motor_Master/control.h create mode 100644 2_Motor_Master/Motor_Master/Motor_Master/statemachine.h create mode 100644 2_Motor_Master/Motor_Master/Motor_Master/utilities.h diff --git a/2_Motor_Master/Motor_Master/Motor_Master/.atmelstart/atmel_start_config.atstart b/2_Motor_Master/Motor_Master/Motor_Master/.atmelstart/atmel_start_config.atstart index 999de40..94e76c3 100644 --- a/2_Motor_Master/Motor_Master/Motor_Master/.atmelstart/atmel_start_config.atstart +++ b/2_Motor_Master/Motor_Master/Motor_Master/.atmelstart/atmel_start_config.atstart @@ -2207,7 +2207,7 @@ drivers: tcc_arch_dbgrun: false tcc_arch_evact0: Event action disabled tcc_arch_evact1: Event action disabled - tcc_arch_lupd: true + tcc_arch_lupd: false tcc_arch_mcei0: false tcc_arch_mcei1: false tcc_arch_mcei2: false @@ -2227,7 +2227,7 @@ drivers: tcc_arch_trgeo: false tcc_arch_wave_duty_val: 500 tcc_arch_wave_per_val: 48 - tcc_arch_wavegen: Single-slope PWM + tcc_arch_wavegen: Dual-slope, interrupt/event at ZERO (DSBOTTOM) tcc_per: 10000 tcc_prescaler: Divide by 2 timer_event_control: true diff --git a/2_Motor_Master/Motor_Master/Motor_Master/EtherCAT_SlaveDef.h b/2_Motor_Master/Motor_Master/Motor_Master/EtherCAT_SlaveDef.h index 1448fd4..41d46db 100644 --- a/2_Motor_Master/Motor_Master/Motor_Master/EtherCAT_SlaveDef.h +++ b/2_Motor_Master/Motor_Master/Motor_Master/EtherCAT_SlaveDef.h @@ -127,41 +127,54 @@ static volatile int16_t *M4_Max_velocity = ((int16_t *)&QSPI_rx_buffer[14]+1) static volatile int16_t *M4_Max_current = ((int16_t *)&QSPI_rx_buffer[15]); static volatile int16_t *M4_Spare = ((int16_t *)&QSPI_rx_buffer[15]+1); -//void update_telemetry(void) -//{ +void update_telemetry(void) +{ //inline int16_t convert_to_mA(volatile float32_t current_PU) //{ //return (int16_t)(current_PU*1000.0f); //} // - //*state = applicationStatus.currentstate; - //*status = applicationStatus.fault; - //*motor_rel_position = Motor1.motor_status.Num_Steps; - //*motor_abs_position = 0; - //*motor_dutyCycle = Motor1.motor_status.duty_cycle; - //*motor_speed = (int16_t)Motor1.motor_status.calc_rpm; - //*motor_torque = 0; - //*motor_currentPHA = convert_to_mA(Motor1.Iphase_pu.A); - //*motor_currentPHB = convert_to_mA(Motor1.Iphase_pu.B); - //*motor_currentPHC = convert_to_mA(Motor1.Iphase_pu.C); - //*motor_currentBUS = convert_to_mA(Motor1.Iphase_pu.Bus); - //*hall_state = Motor1.motor_status.currentHallPattern; - //*Spare_byte1 = Motor1.motor_setpoints.directionOffset; - //*Spare_1 = Motor1.motor_status.actualDirection; - ////*Spare_2 = 0; -//} -// + //*M1_Status = 0; + //*M1_Mode = 0; + + /* Motor 1 */ + *M1_Joint_rel_position = Motor1.motor_status.Num_Steps; + //*M1_Joint_abs_position = ((int16_t *)&QSPI_tx_buffer[1]); + //*M1_Motor_speed = (((int16_t *)&QSPI_tx_buffer[1])+1); + *M1_Motor_current_bus = COMMUTATION_PATTERN[Motor1.motor_status.currentHallPattern + + Motor1.motor_setpoints.directionOffset]; + //*M1_Motor_currentPhA = (((int16_t *)&QSPI_tx_buffer[2])+1); + //*M1_Motor_currentPhB = ((int16_t *)&QSPI_tx_buffer[3]); + //*M1_Motor_currentPhC = (((int16_t *)&QSPI_tx_buffer[3])+1); + *M1_Motor__hallState = Motor1.motor_status.currentHallPattern; + *M1_Motor_dutyCycle = Motor1.motor_status.duty_cycle; + // + /* Motor 2 */ + *M2_Joint_rel_position = Motor2.motor_status.Num_Steps; + //*M1_Joint_abs_position = ((int16_t *)&QSPI_tx_buffer[1]); + //*M1_Motor_speed = (((int16_t *)&QSPI_tx_buffer[1])+1); + *M2_Motor_current_bus = COMMUTATION_PATTERN[Motor2.motor_status.currentHallPattern + + Motor2.motor_setpoints.directionOffset]; + //*M1_Motor_current_bus = ((int16_t *)&QSPI_tx_buffer[2]); + //*M1_Motor_currentPhA = (((int16_t *)&QSPI_tx_buffer[2])+1); + //*M1_Motor_currentPhB = ((int16_t *)&QSPI_tx_buffer[3]); + //*M1_Motor_currentPhC = (((int16_t *)&QSPI_tx_buffer[3])+1); + *M2_Motor__hallState = Motor2.motor_status.currentHallPattern; + *M2_Motor_dutyCycle = Motor2.motor_status.duty_cycle; + +} + void update_setpoints(void) { - volatile uint8_t a = *M1_Control_mode; - volatile uint8_t b = *M1_Control_set; - volatile int16_t c = *M1_Desired_pos; - volatile int16_t d = *M1_Desired_speed; - volatile int16_t e = *M1_Desired_current; - volatile int16_t f = *M1_Max_pos; - volatile int16_t g = *M1_Max_velocity; - volatile int16_t h = *M1_Max_current; - volatile int16_t i = *M1_Spare; + //volatile uint8_t a = *M1_Control_mode; + //volatile uint8_t b = *M1_Control_set; + //volatile int16_t c = *M1_Desired_pos; + //volatile int16_t d = *M1_Desired_speed; + //volatile int16_t e = *M1_Desired_current; + //volatile int16_t f = *M1_Max_pos; + //volatile int16_t g = *M1_Max_velocity; + //volatile int16_t h = *M1_Max_current; + //volatile int16_t i = *M1_Spare; //inline float32_t convert_int_to_PU(volatile int16_t input) //{ //return ((float32_t)(input/1000.0f)); diff --git a/2_Motor_Master/Motor_Master/Motor_Master/Motor_Master.cproj b/2_Motor_Master/Motor_Master/Motor_Master/Motor_Master.cproj index f3cccbf..fa8614f 100644 --- a/2_Motor_Master/Motor_Master/Motor_Master/Motor_Master.cproj +++ b/2_Motor_Master/Motor_Master/Motor_Master/Motor_Master.cproj @@ -29,14 +29,14 @@ 0 - + - + @@ -301,6 +301,7 @@ C:\Users\Nick-XMG\Documents\github\bldc_control_thesis\bldc_firmware_thesis\2_Motor_Master\Motor_Master\Motor_Master\cmsis + C:\Users\ge37vez\Documents\Git Repos\bldc_control_thesis\bldc_firmware_thesis\2_Motor_Master\Motor_Master\Motor_Master\cmsis %24(ProjectDir)\Device_Startup @@ -413,11 +414,11 @@ ../hri - Optimize (-O1) + Optimize more (-O2) True Maximum (-g3) True - -std=gnu99 -mfloat-abi=hard -mfpu=fpv4-sp-d16 + -std=gnu11 -mfloat-abi=hard -mfpu=fpv4-sp-d16 True @@ -427,8 +428,9 @@ - %24(ProjectDir)\Device_Startup C:\Users\Nick-XMG\Documents\github\bldc_control_thesis\bldc_firmware_thesis\2_Motor_Master\Motor_Master\Motor_Master\cmsis + C:\Users\ge37vez\Documents\Git Repos\bldc_control_thesis\bldc_firmware_thesis\2_Motor_Master\Motor_Master\Motor_Master\cmsis + %24(ProjectDir)\Device_Startup True @@ -518,6 +520,9 @@ compile + + compile + compile @@ -572,6 +577,9 @@ compile + + compile + compile @@ -1052,6 +1060,12 @@ compile + + compile + + + compile + diff --git a/2_Motor_Master/Motor_Master/Motor_Master/bldc.c b/2_Motor_Master/Motor_Master/Motor_Master/bldc.c index be2c5a1..78ce2af 100644 --- a/2_Motor_Master/Motor_Master/Motor_Master/bldc.c +++ b/2_Motor_Master/Motor_Master/Motor_Master/bldc.c @@ -5,3 +5,341 @@ * Author: Nick-XMG */ +#include "bldc.h" + +#include "statemachine.h" +#include "utilities.h" + + +void BldcInitStruct(BLDCMotor_t *motor, BLDCMotor_param_t *motor_param) +{ + // ---------------------------------------------------------------------- + // Initialize all voltage and current objects, variables and helpers: + motor->motor_param = motor_param; + motor->motor_status.actualDirection = 0; + motor->motor_setpoints.desiredDirection = 0; + motor->motor_status.duty_cycle = 150; + motor->motor_status.calc_rpm = 0; + motor->motor_status.Num_Steps = 0; + motor->motor_status.cur_comm_step = 0; + motor->motor_status.currentHallPattern = 1; + motor->motor_status.nextHallPattern = 3; + motor->motor_setpoints.directionOffset = 0; + + motor->Iphase_pu.A = 0; + motor->Iphase_pu.B = 0; + motor->Iphase_pu.C = 0; + motor->Iphase_pu.Bus = 0; + motor->Voffset_lsb.A = 0; + motor->Voffset_lsb.B = 0; + motor->timerflags.pwm_cycle_tic = false; + motor->timerflags.control_loop_tic = false; + motor->timerflags.motor_telemetry_flag = false; + motor->timerflags.control_loop_tic = false; + motor->timerflags.adc_readings_ready_tic = false; + + motor->regulation_loop_count = 0; + + + motor->VdcBus_pu = DEVICE_DC_VOLTAGE_V; + motor->VoneByDcBus_pu = 1.0f/DEVICE_DC_VOLTAGE_V; + + motor->motor_setpoints.desired_torque = 0.0; + motor->motor_setpoints.desired_speed = 0; + motor->motor_setpoints.desired_position = 0; + motor->motor_setpoints.max_current = 0.0; + motor->motor_setpoints.max_torque = 0.0; + motor->motor_setpoints.max_velocity = 0; + + //// ------------------------------------------------------------------------------ + //// pi current control init + //// ------------------------------------------------------------------------------ + + //// ------------------------------------------------------------------------------ + //// pi current control init + //// ------------------------------------------------------------------------------ + PI_objectInit(&motor->controllers.Pi_Idc); + float32_t motorLs_H = motor_param->motor_LQ_H * 2.0f; + float32_t motorRs_OHM = motor_param->motor_RS_Ohm * 2.0f; + motor->controllers.Pi_Idc.Kp = PI_calcKp(motorLs_H, DEVICE_SHUNT_CURRENT_A, DEVICE_DC_VOLTAGE_V, DEVICE_ISR_PERIOD_Sec); + motor->controllers.Pi_Idc.Ki = PI_calcKi(motorRs_OHM, motorLs_H, DEVICE_ISR_PERIOD_Sec); + + //// ------------------------------------------------------------------------------ + //// pi velocity control init + //// ------------------------------------------------------------------------------ + PID_objectInit(&motor->controllers.Pid_Speed); + + /* V only Control Gains */ + //motor->controllers.Pid_Speed.Kp = 0.005f; + //motor->controllers.Pid_Speed.Ki = 0.01f; + + /* VI Control Gains */ + //motor->controllers.Pid_Speed.Kp = 0.0003f; + //motor->controllers.Pid_Speed.Ki = 0.001f; + motor->controllers.Pid_Speed.Kp = 0.0005f; + motor->controllers.Pid_Speed.Ki = 0.0f; + motor->controllers.Pid_Speed.Kd = 0.0001f; + + //motor->controllers.Pid_Speed.Ki = 0.0001f; + motor->controllers.Pid_Speed.OutMax_pu = (motor_param->motor_Max_Current_IDC_A); + motor->controllers.Pid_Speed.OutMin_pu = -(motor_param->motor_Max_Current_IDC_A); + + //// ------------------------------------------------------------------------------ + //// pi position control init + //// ------------------------------------------------------------------------------ + PI_objectInit(&motor->controllers.Pi_Pos); + motor->controllers.Pi_Pos.Kp = 40.0f; + motor->controllers.Pi_Pos.Ki = 0.0f; + motor->controllers.Pi_Pos.OutMax_pu = (motor_param->motor_Max_Spd_RPM); + motor->controllers.Pi_Pos.OutMin_pu = -(motor_param->motor_Max_Spd_RPM); + +} + +void exec_commutation(BLDCMotor_t *motor) +{ + // ---------------------------------------------------------------------- + // Read Motor Hall Sensors + // ---------------------------------------------------------------------- + //tic_port(DEBUG_2_PORT); + //motor->motor_status.currentHallPattern = readM1Hall(); + motor->motor_status.currentHallPattern = motor->readHall(); + + // ---------------------------------------------------------------------- + // Multi Motor Register Masking + // ---------------------------------------------------------------------- + //tic_port(DEBUG_2_PORT); + //volatile uint16_t temp_M1 = COMMUTATION_PATTERN_M1[Motor1.motor_status.currentHallPattern + Motor1.motor_setpoints.directionOffset]; + //volatile uint16_t temp_M2 = COMMUTATION_PATTERN_M2[Motor2.motor_status.currentHallPattern + oh ]; + volatile uint16_t temp_M1 = COMMUTATION_PATTERN[motor->motor_status.currentHallPattern + + motor->motor_setpoints.directionOffset]; + // ---------------------------------------------------------------------- + // Set Pattern Buffers + // ---------------------------------------------------------------------- + hri_tcc_write_PATTBUF_reg(motor->motor_param->pwm_desc->device.hw, (hri_tcc_pattbuf_reg_t)temp_M1); + //(Tcc *)(motor->motor_param.pwm_desc->device.hw)->PATTBUF.reg = temp_M1; + //TCC0->PATTBUF.reg = (uint16_t)temp_M2; + //TCC1->PATTBUF.reg = (uint16_t)temp_M1; + + // ---------------------------------------------------------------------- + // Set Calculated Duty Cycles + // ---------------------------------------------------------------------- + hri_tcc_write_CCBUF_CCBUF_bf(motor->motor_param->pwm_desc->device.hw, 0, motor->motor_status.duty_cycle); + //SetM1DutyCycle(Motor1.motor_status.duty_cycle); + //SetM2DutyCycle(Motor1.motor_status.duty_cycle); + + motor->motor_status.cur_comm_step = MOTOR_COMMUTATION_STEPS[motor->motor_status.currentHallPattern]; + volatile int8_t step_change1 = motor->motor_status.cur_comm_step - motor->motor_status.prev_comm_step; + + switch(step_change1) + { + case 1: case -5: + motor->motor_status.Num_Steps = motor->motor_status.Num_Steps+1; + motor->motor_status.actualDirection = CW; + //Motor1.motor_setpoints.directionOffset = DIRECTION_CW_OFFSET; + break; + case -1: case 5: + motor->motor_status.Num_Steps = motor->motor_status.Num_Steps-1; + motor->motor_status.actualDirection = CCW; + //Motor1.motor_setpoints.directionOffset = DIRECTION_CCW_OFFSET; + break; + default: + // do nothing + break; + } + motor->motor_status.prev_comm_step = motor->motor_status.cur_comm_step; + //toc_port(DEBUG_2_PORT); +} + +void process_currents(BLDCMotor_t *motor1, BLDCMotor_t *motor2) +{ + Motor1.timerflags.adc_readings_ready_tic = false; + Motor2.timerflags.adc_readings_ready_tic = false; + ////tic_port(DEBUG_2_PORT); + //volatile int16_t phase_A_current_raw, phase_B_current_raw; + // + ///* Motor 1 */ + //phase_A_current_raw = (adc_res[0] - Motor1.Voffset_lsb.A); + //phase_B_current_raw = (adc_res[1] - Motor1.Voffset_lsb.B)*-1; + //// Covert from LSB to PU (A) and filter out small readings + //Motor1.Iphase_pu.A = phase_A_current_raw * LSB_TO_PU; + //Motor1.Iphase_pu.B = phase_B_current_raw * LSB_TO_PU; + //// i_c = -i_a - i_b because i_a + i_b + i_c = 0 + //Motor1.Iphase_pu.C = -Motor1.Iphase_pu.A - Motor1.Iphase_pu.B; + // + ///* Motor 2 */ + //phase_A_current_raw = (adc_res[2] - Motor2.Voffset_lsb.A); + //phase_B_current_raw = (adc_res[3] - Motor2.Voffset_lsb.B)*-1; + //// Covert from LSB to PU (A) and filter out small readings + //Motor2.Iphase_pu.A = phase_A_current_raw * LSB_TO_PU; + //Motor2.Iphase_pu.B = phase_B_current_raw * LSB_TO_PU; + //// i_c = -i_a - i_b because i_a + i_b + i_c = 0 + //Motor2.Iphase_pu.C = -Motor2.Iphase_pu.A - Motor2.Iphase_pu.B; + + // Set Current Loop Flag + Motor1.timerflags.current_loop_tic = true; + Motor2.timerflags.current_loop_tic = true; +} + +void calculate_motor_speed(BLDCMotor_t *motor) +{ + //tic_port(DEBUG_2_PORT); + volatile uint32_t temp_rpm = 0; + hri_tccount32_read_CC_reg(TC0, 0); /* Read CC0 but throw away)*/ + volatile uint32_t period_after_capture = hri_tccount32_read_CC_reg(TC0, 1); + if((period_after_capture > UINT32_MAX)|| (period_after_capture > 10712046)) { + Motor1.motor_status.calc_rpm = 0; + } else { + //uint32_t test = (SPEEDFACTOR, period_after_capture); + //temp_rpm = SPEEDFACTOR / period_after_capture; + //tic_port(DEBUG_3_PORT); + temp_rpm = HZ_TO_RPM / (period_after_capture*motor->motor_param->motor_commutationStates); + //temp_rpm = HZ_TO_RPM * period_after_capture; + //toc_port(DEBUG_3_PORT); + } + + if(Motor1.motor_status.actualDirection == CCW) /* Changed from CCW */ + { + //*motor_speed = -1* Motor1.calc_rpm; + temp_rpm = -1 * temp_rpm; + } else { + //*motor_speed = Motor1.calc_rpm; + temp_rpm = temp_rpm; + } + + Motor1.motor_status.calc_rpm = (int16_t)temp_rpm; + //toc_port(DEBUG_2_PORT); + + //#ifdef AVERAGE_SPEED_MEASURE + //// To avoid noise an average is realized on 8 samples + //speed_average += temp_rpm; + //if(count >= n_SAMPLE) + //{ + //count = 1; + //Motor1.motor_status.calc_rpm = (speed_average >> 3); // divide by 32 + ////Motor1.motor_status.calc_rpm = (speed_average); // divide by 32 + //speed_average = 0; + ////*Spare_byte1 = motorState.actualDirection; + //if(Motor1.motor_status.actualDirection == CCW) /* Changed from CCW */ + //{ + ////*motor_speed = -1* Motor1.calc_rpm; + //Motor1.motor_status.calc_rpm = -1* Motor1.motor_status.calc_rpm; + //} else { + ////*motor_speed = Motor1.calc_rpm; + //Motor1.motor_status.calc_rpm = Motor1.motor_status.calc_rpm; + //} + //return; + //} + //else count++; + //#else + //Motor1.motor_status.calc_rpm = (int16_t)temp_rpm; + //#endif + //toc_port(DEBUG_2_PORT); +} + + +//------------------------------------------------------------------------------ +// pi current control +//------------------------------------------------------------------------------ +void BLDC_runCurrentCntl(BLDCMotor_t *motor, const float32_t curfbk, const float32_t curRef) +{ + motor->controllers.Pi_Idc.Fbk_pu = f_clamp(curfbk, -DEVICE_SHUNT_CURRENT_A, DEVICE_SHUNT_CURRENT_A); // Clamped to max current sensor readingspeedfbk; + motor->controllers.Pi_Idc.Ref_pu = f_clamp(curRef, -motor->motor_param->motor_Max_Current_IDC_A, + motor->motor_param->motor_Max_Current_IDC_A); // Clamp desired to Motor Max Current i_ref_clamped; + + //*Spare_1 = (int16_t)(motor->controllers.Pi_Idc.Ref_pu * 1000); // Send Req Current to TC + + motor->controllers.Pi_Idc.OutMax_pu = motor->VdcBus_pu; + motor->controllers.Pi_Idc.OutMin_pu = -motor->VdcBus_pu; + PI_run_series(&motor->controllers.Pi_Idc); + + if(motor->controllers.Pi_Idc.Out_pu > 0) { + motor->motor_setpoints.desiredDirection = 0; + motor->motor_setpoints.directionOffset = 0; + } else { + motor->motor_setpoints.desiredDirection = 1; + motor->motor_setpoints.directionOffset = 8; + } + + volatile float32_t duty_pu = f_abs((motor->controllers.Pi_Idc.Out_pu * motor->VoneByDcBus_pu)); + motor->motor_status.duty_cycle = (uint16_t)f_clamp(duty_pu * (float32_t)MAX_PWM, 0.0f, (float32_t)MAX_PWM); + // Remove Low duty cycle values + //if(duty_cycle < 80.0) motor->duty_cycle = (uint16_t)0; + //else motor->duty_cycle = (uint16_t)duty_cycle; + +} + +//// ------------------------------------------------------------------------------ +// Speed Control: Input in RPM units (int16_t) +//------------------------------------------------------------------------------ +void BLDC_runSpeedCntl(BLDCMotor_t *motor, const float32_t speedfbk, const float32_t speedRef) +{ + //tic_port(DEBUG_3_PORT); + motor->controllers.Pid_Speed.Fbk_pu = speedfbk; + motor->controllers.Pid_Speed.Ref_pu = f_clamp(speedRef, -motor->motor_param->motor_Max_Spd_RPM, + motor->motor_param->motor_Max_Spd_RPM); + + if (applicationStatus.currentstate == MOTOR_V_CTRL_STATE) + { + /* Output Pu in Volts (PWM %) */ + motor->controllers.Pid_Speed.OutMax_pu = motor->VdcBus_pu; + motor->controllers.Pid_Speed.OutMin_pu = -motor->VdcBus_pu; + + PID_run_parallel(&motor->controllers.Pid_Speed); + + if(motor->controllers.Pid_Speed.Out_pu > 0) { + motor->motor_setpoints.desiredDirection = 0; + motor->motor_setpoints.directionOffset = 0; + } else { + motor->motor_setpoints.desiredDirection = 1; + motor->motor_setpoints.directionOffset = 8; + } + /* Process unit is Volts */ + volatile float32_t duty_pu = f_abs((motor->controllers.Pid_Speed.Out_pu * motor->VoneByDcBus_pu)); + volatile duty_cycle = f_clamp(duty_pu * (float32_t)MAX_PWM, 0.0f, (float32_t)MAX_PWM); + motor->motor_status.duty_cycle = (uint16_t)duty_cycle; + } else { + /* Pu in Current (Amps) */ + motor->controllers.Pid_Speed.OutMax_pu = (motor->motor_param->motor_Max_Current_IDC_A); + motor->controllers.Pid_Speed.OutMin_pu = -(motor->motor_param->motor_Max_Current_IDC_A); + PID_run_parallel(&motor->controllers.Pid_Speed); + motor->controllers.Pi_Idc.Ref_pu = motor->controllers.Pid_Speed.Out_pu; + } + //toc_port(DEBUG_3_PORT); +} + +//// ------------------------------------------------------------------------------ +// Position Control:Input in Hall step units (int16_t) +//------------------------------------------------------------------------------ +void BLDC_runPosCntl(BLDCMotor_t *motor, const int16_t posfbk, const int16_t posRef) +{ + /* Output Pu in RPM */ + motor->controllers.Pi_Pos.OutMax_pu = motor->motor_param->motor_Max_Spd_RPM; + motor->controllers.Pi_Pos.OutMin_pu = -motor->motor_param->motor_Max_Spd_RPM; + motor->controllers.Pi_Pos.Fbk_pu = posfbk; + motor->controllers.Pi_Pos.Ref_pu = posRef; + PI_run_series(&motor->controllers.Pi_Pos); + motor->controllers.Pid_Speed.Ref_pu = motor->controllers.Pi_Pos.Out_pu; +} + +uint8_t readHallSensorM1(void) +{ + volatile uint8_t a = gpio_get_pin_level(M1_HALL_A_PIN); + volatile uint8_t b = gpio_get_pin_level(M1_HALL_B_PIN); + volatile uint8_t c = gpio_get_pin_level(M1_HALL_C_PIN); + + return ((a << 2) | + (b << 1) | + (c << 0)); + +} + +uint8_t readHallSensorM2(void) +{ + volatile uint8_t a = gpio_get_pin_level(M2_HALL_A_PIN); + volatile uint8_t b = gpio_get_pin_level(M2_HALL_B_PIN); + volatile uint8_t c = gpio_get_pin_level(M2_HALL_C_PIN); + + return ((a << 2) | + (b << 1) | + (c << 0)); +} \ No newline at end of file diff --git a/2_Motor_Master/Motor_Master/Motor_Master/bldc.h b/2_Motor_Master/Motor_Master/Motor_Master/bldc.h index d86572f..9ffba42 100644 --- a/2_Motor_Master/Motor_Master/Motor_Master/bldc.h +++ b/2_Motor_Master/Motor_Master/Motor_Master/bldc.h @@ -5,7 +5,6 @@ * Author: Nick-XMG */ - #ifndef BLDC_H_ #define BLDC_H_ @@ -13,7 +12,7 @@ // header files // ---------------------------------------------------------------------- #include "atmel_start.h" -#include "arm_math.h" +#include "bldc_types.h" #include "motorparameters.h" #define PWM_TOP (1000) @@ -25,68 +24,78 @@ #define CCW (1) //ABC #define DIRECTION_CCW_OFFSET (8) //CBA +/* if the Hall sensor reads 0x0 or 0x7 that means either one of the hall sensor is damaged or disconnected*/ +#define INVALID_HALL_0 (0U) +#define INVALID_HALL_7 (7U) -static uint32_t adc_seq_regs[5] = {0x1800, 0x1806, 0x1807, 0x1808, 0x1809}; -static volatile uint16_t adc_res[5] = {0}; +// ---------------------------------------------------------------------- +// ADC Parameters +// ---------------------------------------------------------------------- +#define ADC_VOLTAGE_REFERENCE (3.3f) +#define ADC_RESOLUTION (12) +#define ADC_MAX_COUNTS (1<Group[M2_HALL_A_GROUP].IN.reg & M2_HALL_A_PORT)>>(M2_HALL_A_LSR)); + ////motor_read = (motor_read & M2_HALL_B_MASK) | (uint8_t)((PORT->Group[M2_HALL_B_GROUP].IN.reg & M2_HALL_B_PORT)>>(M2_HALL_B_LSR)); + ////motor_read = (motor_read & M2_HALL_C_MASK) | (uint8_t)((PORT->Group[M2_HALL_C_GROUP].IN.reg & M2_HALL_C_PORT)>>(M2_HALL_C_LSR)); + //// + ////return motor_read; + // + //Motor1. + // + //volatile uint8_t a = gpio_get_pin_level(motor->motor_param->hallPins.hallA); + ////volatile uint8_t b = gpio_get_pin_level(motor->motor_param->hallsensors[1]); + ////volatile uint8_t c = gpio_get_pin_level(motor->motor_param->hallsensors[2]); + //// + ////return ((a << 2) | + ////(b << 1) | + ////(c << 0)); +//} #endif /* BLDC_H_ */ \ No newline at end of file diff --git a/2_Motor_Master/Motor_Master/Motor_Master/bldc_types.h b/2_Motor_Master/Motor_Master/Motor_Master/bldc_types.h new file mode 100644 index 0000000..3085cd6 --- /dev/null +++ b/2_Motor_Master/Motor_Master/Motor_Master/bldc_types.h @@ -0,0 +1,109 @@ +/* + * bldc_types.h + * + * Created: 8/5/2021 9:40:45 AM + * Author: ge37vez + */ + + +#ifndef BLDC_TYPES_H_ +#define BLDC_TYPES_H_ + +#include "atmel_start.h" +#include "control.h" +#include "motorparameters.h" + +// ---------------------------------------------------------------------- +// function Pointer +// ---------------------------------------------------------------------- +typedef uint8_t (*readHallSensor)(void); + +// ---------------------------------------------------------------------- +// Type Definitions +// ---------------------------------------------------------------------- +volatile typedef struct +{ + volatile float32_t A; // Phase A + volatile float32_t B; // Phase B + volatile float32_t C; // Phase C + volatile float32_t Bus; // Currently Active Phase Current +} MOTOR_3PHASES_t; + +volatile typedef struct +{ + volatile int16_t A; // Phase A measured offset + volatile int16_t B; // Phase B measured offset +} MOTOR_phase_offset_t; + +volatile typedef struct timerflags +{ + volatile bool pwm_cycle_tic; + volatile bool current_loop_tic; + volatile bool control_loop_tic; + volatile bool adc_readings_ready_tic; + volatile bool motor_telemetry_flag; +} TIMERflags_t; + +volatile typedef struct +{ + volatile PI_t Pi_Idc; + volatile PID_t Pid_Speed; + volatile PI_t Pi_Pos; +} MOTOR_Control_Structs; + +volatile typedef struct +{ + volatile uint8_t desiredDirection; //! The desired direction of rotation. + volatile uint8_t directionOffset; + volatile float32_t desired_torque; + volatile int16_t desired_speed; + volatile int16_t desired_position; + volatile float32_t max_torque; + volatile float32_t max_current; + volatile int16_t max_velocity; +} MOTOR_Setpoints; + +volatile typedef struct +{ + volatile uint8_t actualDirection; //! The actual direction of rotation. + volatile uint16_t duty_cycle; + volatile float32_t calc_rpm; + volatile int32_t* Num_Steps; + /* Hall States */ + volatile uint8_t prevHallPattern; + volatile uint8_t currentHallPattern; + volatile uint8_t nextHallPattern; + /* Commutation State */ + volatile uint8_t cur_comm_step; + volatile uint8_t prev_comm_step; +} MOTOR_Status; + +// ---------------------------------------------------------------------- +// Main BLDC Struct +// ---------------------------------------------------------------------- +volatile typedef struct BLDCmotor +{ + /* Hardware */ + const uint32_t current_sensor_channels[2]; + BLDCMotor_param_t *motor_param; + /* Status */ + MOTOR_Status motor_status; + /* Measured Values */ + volatile MOTOR_3PHASES_t Iphase_pu; + volatile MOTOR_phase_offset_t Voffset_lsb; + volatile float32_t VdcBus_pu; + volatile float32_t VoneByDcBus_pu; + /* Motor Flags */ + volatile TIMERflags_t timerflags; + volatile uint8_t regulation_loop_count; + /* Controllers */ + volatile MOTOR_Control_Structs controllers; + /* Setpoints */ + volatile MOTOR_Setpoints motor_setpoints; + /* Function Pointers*/ + readHallSensor readHall; +} BLDCMotor_t; + + + +#endif /* BLDC_TYPES_H_ */ \ No newline at end of file diff --git a/2_Motor_Master/Motor_Master/Motor_Master/configuration.h b/2_Motor_Master/Motor_Master/Motor_Master/configuration.h index 7e1061d..1818dce 100644 --- a/2_Motor_Master/Motor_Master/Motor_Master/configuration.h +++ b/2_Motor_Master/Motor_Master/Motor_Master/configuration.h @@ -21,40 +21,43 @@ inline static void configure_tcc_pwm(void) { /* TCC0 */ - //hri_tcc_set_WEXCTRL_OTMX_bf(TCC0, 0); + hri_tcc_set_WEXCTRL_OTMX_bf(TCC0, 0x02); - //hri_tcc_set_WAVE_POL0_bit(TCC0); - //hri_tcc_set_WAVE_POL1_bit(TCC0); - //hri_tcc_set_WAVE_POL2_bit(TCC0); - //hri_tcc_set_WAVE_POL3_bit(TCC0); - //hri_tcc_set_WAVE_POL4_bit(TCC0); - //hri_tcc_set_WAVE_POL5_bit(TCC0); - //hri_tcc_write_CC_CC_bf(TCC0, 0, 0); - //hri_tcc_write_CC_CC_bf(TCC0, 1, 0); - //hri_tcc_write_CC_CC_bf(TCC0, 2, 0); - //hri_tcc_write_CC_CC_bf(TCC0, 3, 0); - //hri_tcc_write_CC_CC_bf(TCC0, 4, 0); - //hri_tcc_write_CC_CC_bf(TCC0, 5, 0); + hri_tcc_set_WAVE_POL0_bit(TCC0); + hri_tcc_set_WAVE_POL1_bit(TCC0); + hri_tcc_set_WAVE_POL2_bit(TCC0); + hri_tcc_set_WAVE_POL3_bit(TCC0); + hri_tcc_set_WAVE_POL4_bit(TCC0); + hri_tcc_set_WAVE_POL5_bit(TCC0); + hri_tcc_write_CC_CC_bf(TCC0, 0, 150); + hri_tcc_write_CC_CC_bf(TCC0, 1, 150); + hri_tcc_write_CC_CC_bf(TCC0, 2, 150); + hri_tcc_write_CC_CC_bf(TCC0, 3, 150); + hri_tcc_write_CC_CC_bf(TCC0, 4, 150); + hri_tcc_write_CC_CC_bf(TCC0, 5, 150); hri_tcc_write_PER_reg(TCC0,1200); + //hri_tcc_write_CCBUF_CCBUF_bf(TCC0, 0,250); hri_tcc_write_CTRLA_ENABLE_bit(TCC0, 1 << TCC_CTRLA_ENABLE_Pos); /* TCC1 */ - //hri_tcc_set_WEXCTRL_OTMX_bf(TCC1, 3); - //hri_tcc_write_CC_CC_bf(TCC1, 0, 0); - //hri_tcc_write_CC_CC_bf(TCC1, 1, 0); - //hri_tcc_write_CC_CC_bf(TCC1, 2, 0); - //hri_tcc_write_CC_CC_bf(TCC1, 3, 0); - ////hri_tcc_write_CC_CC_bf(TCC1, 0, 0); + hri_tcc_set_WEXCTRL_OTMX_bf(TCC1, 0x02); + hri_tcc_write_CC_CC_bf(TCC1, 0, 150); + hri_tcc_write_CC_CC_bf(TCC1, 1, 150); + hri_tcc_write_CC_CC_bf(TCC1, 2, 150); + hri_tcc_write_CC_CC_bf(TCC1, 3, 150); + hri_tcc_write_CC_CC_bf(TCC0, 4, 150); + hri_tcc_write_CC_CC_bf(TCC0, 5, 150); // ////pwm_set_parameters(&TCC_PWM, 1000, 250); - //hri_tcc_set_WAVE_POL0_bit(TCC1); - //hri_tcc_set_WAVE_POL1_bit(TCC1); - //hri_tcc_set_WAVE_POL2_bit(TCC1); - //hri_tcc_set_WAVE_POL3_bit(TCC1); - //hri_tcc_set_WAVE_POL4_bit(TCC1); - //hri_tcc_set_WAVE_POL5_bit(TCC1); + hri_tcc_set_WAVE_POL0_bit(TCC1); + hri_tcc_set_WAVE_POL1_bit(TCC1); + hri_tcc_set_WAVE_POL2_bit(TCC1); + hri_tcc_set_WAVE_POL3_bit(TCC1); + hri_tcc_set_WAVE_POL4_bit(TCC1); + hri_tcc_set_WAVE_POL5_bit(TCC1); hri_tcc_write_PER_reg(TCC1,1200); + //hri_tcc_write_CCBUF_CCBUF_bf(TCC1, 0, 250); hri_tcc_clear_CTRLA_ENABLE_bit(TCC1); hri_tcc_write_CTRLA_MSYNC_bit(TCC1, true); //hri_tcc_write_CTRLA_ENABLE_bit(TCC1, 1 << TCC_CTRLA_ENABLE_Pos); /* Enable: enabled */ @@ -90,7 +93,7 @@ inline void adc_dmac_sequence_init() */ _dma_set_source_address(DMAC_CHANNEL_ADC_SEQ, (const void *)adc_seq_regs); _dma_set_destination_address(DMAC_CHANNEL_ADC_SEQ, (const void *)&ADC1->DSEQDATA.reg); - _dma_set_data_amount(DMAC_CHANNEL_ADC_SEQ, 5); + _dma_set_data_amount(DMAC_CHANNEL_ADC_SEQ, 4); _dma_set_next_descriptor(DMAC_CHANNEL_ADC_SEQ, DMAC_CHANNEL_ADC_SEQ); _dma_enable_transaction(DMAC_CHANNEL_ADC_SEQ, false); //_dma_get_channel_resource(&adc_dmac_sequence_resource, DMAC_CHANNEL_ADC_SEQ); @@ -106,7 +109,7 @@ inline void adc_sram_dmac_init() * next descriptor address, data count and Enable the DMAC Channel */ _dma_set_source_address(DMAC_CHANNEL_ADC_SRAM, (const void *)&ADC1->RESULT.reg); _dma_set_destination_address(DMAC_CHANNEL_ADC_SRAM, (const void *)adc_res); - _dma_set_data_amount(DMAC_CHANNEL_ADC_SRAM, 5); + _dma_set_data_amount(DMAC_CHANNEL_ADC_SRAM, 4); _dma_set_irq_state(DMAC_CHANNEL_ADC_SRAM, DMA_TRANSFER_COMPLETE_CB, true); _dma_get_channel_resource(&adc_sram_dma_resource, DMAC_CHANNEL_ADC_SRAM); adc_sram_dma_resource[0].dma_cb.transfer_done = adc_sram_dma_callback; diff --git a/2_Motor_Master/Motor_Master/Motor_Master/control.h b/2_Motor_Master/Motor_Master/Motor_Master/control.h new file mode 100644 index 0000000..3ccc2f2 --- /dev/null +++ b/2_Motor_Master/Motor_Master/Motor_Master/control.h @@ -0,0 +1,256 @@ +/* + * pi.h + * + * Created: 01/02/2021 21:36:11 + * Author: Nick-XMG + */ +#ifndef CONTROL_H_ +#define CONTROL_H_ + +// ---------------------------------------------------------------------- +// history +// ---------------------------------------------------------------------- +// 01.02.2021 - initial Revision + +// ---------------------------------------------------------------------- +// header files +// ---------------------------------------------------------------------- +#include "arm_math.h" +#include "atmel_start.h" +#include "utilities.h" +// ---------------------------------------------------------------------- +// #defines +// ---------------------------------------------------------------------- +// ---------------------------------------------------------------------- +// global variables +// ---------------------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { + #endif + +/* PI Structure */ +typedef volatile struct +{ + volatile float32_t Kp; // the proportional gain for the PI controller + volatile float32_t Ki; // the integral gain for the PI controller + + volatile float32_t Ref_pu; // the reference value [pu] + volatile float32_t Fbk_pu; // the feedback value [pu] + volatile float32_t Ff_pu; // the feedForward value [pu] + + volatile float32_t OutMin_pu; // the saturation low limit for the controller output [pu] + volatile float32_t OutMax_pu; // the saturation high limit for the controller output [pu] + volatile float32_t Out_pu; // the controller output [pu] + + volatile float32_t Ui; // the integrator value for the PI controller + volatile float32_t error; // the integrator value for the PI controller + volatile bool SatFlag; // flag to signal controller saturation +} PI_t; + +/* PID Structure */ +typedef volatile struct +{ + volatile float32_t Kp; //!< the proportional gain for the PID controller + volatile float32_t Ki; //!< the integral gain for the PID controller + volatile float32_t Kd; //!< the derivative gain for the PID controller + + volatile float32_t Ref_pu; //!< the reference input value + volatile float32_t Fbk_pu; //!< the feedback input value + volatile float32_t Ff_pu; //!< the feedforward input value + + volatile float32_t OutMin_pu; //!< the minimum output value allowed for the PID controller + volatile float32_t OutMax_pu; //!< the maximum output value allowed for the PID controller + volatile float32_t Out_pu; // the controller output [pu] + + volatile float32_t Ui; //!< the integrator start value for the PID controller + volatile float32_t Ud; + volatile float32_t error; // the integrator value for the PI controller + + //FILTER_FO_Handle derFilterHandle; //!< the derivative filter handle + //FILTER_FO_Obj derFilter; //!< the derivative filter object +} PID_t; + + +// ---------------------------------------------------------------------- +// functions +// ---------------------------------------------------------------------- +// function to set default values for the object + +//inline float32_t clamp(const float32_t d, const float32_t min, const float32_t max) { + //const float32_t t = d < min ? min : d; + //return t > max ? max : t; +//} + + +inline void PI_objectInit(volatile PI_t *pPi_obj) +{ + PI_t *obj = (PI_t *)pPi_obj; + + // Function initializes the object with default values + //fix16_t Kp = fix16_from_float32_t(1.0); + obj->Kp = 0.0f; + obj->Ki = 0.0f; + obj->Fbk_pu = 0.0f; + obj->Ref_pu = 0.0f; + obj->Ff_pu = 0.0f; + obj->Out_pu = 0.0f; + obj->OutMax_pu = 0.0f; + obj->OutMin_pu = 0.0f; + obj->Ui = 0.0f; + obj->SatFlag = false; +} + +inline void PID_objectInit(volatile PID_t *pPiD_obj) +{ + PID_t *obj = (PID_t *)pPiD_obj; + + // Function initializes the object with default values + //fix16_t Kp = fix16_from_float32_t(1.0); + obj->Kp = 0.0f; + obj->Ki = 0.0f; + obj->Kd = 0.0f; + obj->Fbk_pu = 0.0f; + obj->Ref_pu = 0.0f; + obj->Ff_pu = 0.0f; + obj->Out_pu = 0.0f; + obj->OutMax_pu = 0.0f; + obj->OutMin_pu = 0.0f; + obj->Ui = 0.0f; + obj->Ud = 0.0f; +} + +// ---------------------------------------------------------------------- +// PI Calculation +// ---------------------------------------------------------------------- +static inline void PI_run_series(volatile PI_t *pPi_obj) +{ + PI_t *obj = (PI_t *)pPi_obj; + volatile float32_t Up; + + // Compute the controller error + obj->error = obj->Ref_pu - obj->Fbk_pu; + + // Compute the proportional term + Up = obj->Kp *obj->error; + + // Compute the integral term in series form and saturate + obj->Ui = f_clamp((obj->Ui + (obj->Ki * Up)), obj->OutMin_pu, obj->OutMax_pu); + + // Saturate the output + obj->Out_pu = f_clamp((Up + obj->Ui + obj->Ff_pu), obj->OutMin_pu, obj->OutMax_pu); +} + +static inline void PI_run_parallel(volatile PI_t *pPi_obj) +{ + PI_t *obj = (PI_t *)pPi_obj; + volatile float32_t Up; + + // Compute the controller error + obj->error = obj->Ref_pu - obj->Fbk_pu; + + // Compute the proportional term + Up = obj->Kp * obj->error; + + // Compute the integral term in parallel form and saturate + obj->Ui = f_clamp((obj->Ui + (obj->Ki * obj->error)), obj->OutMin_pu, obj->OutMax_pu); + + obj->Out_pu = f_clamp((Up + obj->Ui + obj->Ff_pu), obj->OutMin_pu, obj->OutMax_pu); // Saturate the output +} // end of PI_run_parallel() function + + +// ---------------------------------------------------------------------- +// PID Calculation +// ---------------------------------------------------------------------- +static inline void PID_run_series(volatile PID_t *pPid_obj) +{ + PID_t *obj = (PID_t *)pPid_obj; + volatile float32_t Up, Ud_tmp; + + // Compute the controller error + obj->error = obj->Ref_pu - obj->Fbk_pu; + + // Compute the proportional term + Up = obj->Kp * obj->error; + + if(obj->Ki>0.0f){ + // Compute the integral term in parallel form and saturate + obj->Ui = f_clamp((obj->Ui + (obj->Ki * Up)), obj->OutMin_pu, obj->OutMax_pu); + } + + Ud_tmp = obj->Kd * obj->Ui; // Compute the derivative term + + obj->Ud = Ud_tmp; // Replace with filter + + obj->Out_pu = f_clamp((Up + obj->Ui + obj->Ud + obj->Ff_pu), obj->OutMin_pu, obj->OutMax_pu); // Saturate the output + +} + +static inline void PID_run_parallel(volatile PID_t *pPid_obj) +{ + PID_t *obj = (PID_t *)pPid_obj; + volatile float32_t Up, Ud_tmp; + + + // Compute the controller error + obj->error = obj->Ref_pu - obj->Fbk_pu; + + // Compute the proportional term + Up = obj->Kp * obj->error; + + if(obj->Ki>0.0f){ + // Compute the integral term in parallel form and saturate + obj->Ui = f_clamp((obj->Ui + (obj->Ki * obj->error)), obj->OutMin_pu, obj->OutMax_pu); + } + + Ud_tmp = obj->Kd * obj->error; // Compute the derivative term + + obj->Ud = Ud_tmp; // Replace with filter + + obj->Out_pu = f_clamp((Up + obj->Ui + obj->Ud + obj->Ff_pu), obj->OutMin_pu, obj->OutMax_pu); // Saturate the output +} + + +// ---------------------------------------------------------------------- +// Calculate Current Parameters +// ---------------------------------------------------------------------- + +static inline float32_t PI_calcKp(const float32_t Ls_H, const float32_t deviceCurrent_A, const float32_t deviceVoltage_V, +const float32_t deviceCtrlPeriode_Sec) +{ + // calculation is based on "Betragsoptimum" + // Kp = Ls/(2*tau) + float32_t x1; + float32_t y1; + float32_t Kp; + + // multiplication with deviceCurrent_A is to get per unit values + x1 = (float32_t)(Ls_H * deviceCurrent_A); + + y1 = (float32_t)(2.0f * deviceCtrlPeriode_Sec); + + // multiplication with deviceVoltage_V is to get per unit values + y1 = (float32_t)(y1 * deviceVoltage_V); + + Kp = (x1 / y1); + return Kp; +} + +static inline float32_t PI_calcKi(const float32_t Rs_Ohm, const float32_t Ls_H, const float32_t deviceCtrlPeriode_Sec) +{ + // calculation is based on "TI - MotorWare's documentation" + float32_t RsByLs = (float32_t)(Rs_Ohm / Ls_H); + float32_t Ki = RsByLs * deviceCtrlPeriode_Sec; + //fix16_t Ki = 0; + return Ki; +} + +// ---------------------------------------------------------------------- +// end of file +// ---------------------------------------------------------------------- + +#ifdef __cplusplus +} +#endif /* extern "C" */ +#endif /* BLDC_PI_H_ */ + diff --git a/2_Motor_Master/Motor_Master/Motor_Master/interrupts.h b/2_Motor_Master/Motor_Master/Motor_Master/interrupts.h index 0b79e1c..a9f39cc 100644 --- a/2_Motor_Master/Motor_Master/Motor_Master/interrupts.h +++ b/2_Motor_Master/Motor_Master/Motor_Master/interrupts.h @@ -22,6 +22,7 @@ static void pwm_cb(const struct pwm_descriptor *const descr) void adc_sram_dma_callback(struct _dma_resource *adc_dma_res) { volatile uint8_t x = 1; + Motor1.timerflags.adc_readings_ready_tic = true; //tic_port(DEBUG_2_PORT); //Motor1.timerflags.adc_readings_ready_tic = true; //tic_port(DEBUG_2_PORT); diff --git a/2_Motor_Master/Motor_Master/Motor_Master/main.c b/2_Motor_Master/Motor_Master/Motor_Master/main.c index c90a5af..29884d2 100644 --- a/2_Motor_Master/Motor_Master/Motor_Master/main.c +++ b/2_Motor_Master/Motor_Master/Motor_Master/main.c @@ -4,10 +4,12 @@ // Header Files // ---------------------------------------------------------------------- #include "bldc.h" +#include "bldc_types.h" #include "EtherCAT_QSPI.h" #include "EtherCAT_SlaveDef.h" #include "configuration.h" #include "interrupts.h" +#include "statemachine.h" /** * Example of using TIMER_0. @@ -15,8 +17,8 @@ static void One_ms_cycle_callback(const struct timer_task *const timer_task) { if ((ecat_state == wait2)|(ecat_state == wait)) ecat_state= write_fifo; - run_ECAT =true; + update_telemetry(); //run_ECAT = true; } @@ -41,11 +43,84 @@ void enable_NVIC_IRQ(void) //NVIC_EnableIRQ(EIC_5_IRQn); } +inline void CONTROLLER_StateMachine(void) +{ + Motor1.timerflags.current_loop_tic = false; + + if (applicationStatus.fault) + { + applicationStatus.previousstate = applicationStatus.currentstate; + applicationStatus.currentstate = FAULT; + } + + switch(applicationStatus.currentstate) /* process current motor state*/ + { + case SYSTEM_INIT: + /* Toggle driver reset Latch */ + gpio_set_pin_level(M1_RST, true); + gpio_set_pin_level(M1_RST, false); + gpio_set_pin_level(M2_RST, true); + gpio_set_pin_level(M2_RST, false); + /* Update State Variables */ + applicationStatus.previousstate = applicationStatus.currentstate; + applicationStatus.currentstate = SYSTEM_IDLE; + break; + case SYSTEM_IDLE: + /* If received MOTOR START command, move to MOTOR_INIT */ + //if(HostController.StartStopMotor == 0) + //{ + applicationStatus.previousstate = applicationStatus.currentstate; + applicationStatus.currentstate = MOTOR_IDLE; + //} + break; + case MOTOR_IDLE: + applicationStatus.previousstate = applicationStatus.currentstate; + applicationStatus.currentstate = MOTOR_OPEN_LOOP_STATE; + //applicationStatus.currentstate = MOTOR_V_CTRL_STATE; + break; + case MOTOR_OPEN_LOOP_STATE: + //volatile uint16_t x = 0; + break; + case FAULT: + //DisableGateDrivers(&Motor1); + switch(applicationStatus.fault) + { + case NOFAULT: + break; + case HALLSENSORINVALID: + break; + case MOTOR_STALL: + break; + case VOLTAGE: + break; + case OVERCURRENT: + break; + case GATE_DRIVER: + break; + case UNKNOWN: + break; + default: break; + }// End switch(switch(applicationStatus.fault)) + case COMMSTEST: + break; + default: break; + } // End switch(applicationStatus.currentstate) + + exec_commutation(&Motor1); + exec_commutation(&Motor2); +} // inline void CONTROLLER_StateMachine(void) + int main(void) { volatile uint8_t m2_hall, m1_hall, x= 0; /* Initializes MCU, drivers and middleware */ atmel_start_init(); + //initMotorParameters(); + BldcInitStruct(&Motor1, &FH_22mm24BXTR); + BldcInitStruct(&Motor2, &FH_32mm24BXTR); + Motor1.readHall = &readHallSensorM1; + Motor2.readHall = &readHallSensorM2; + config_qspi(); One_ms_timer_init(); configure_tcc_pwm(); @@ -57,12 +132,15 @@ int main(void) /* Replace with your application code */ while (1) { //delay_ms(100); - *M1_Motor__hallState = readM1Hall(); - *M2_Motor__hallState = readM2Hall(); + //*M1_Motor__hallState = readM1Hall(); + //*M2_Motor__hallState = readM2Hall(); //x += 1; //comms_check(); //update_setpoints(); if (run_ECAT) ECAT_STATE_MACHINE(); - + if (Motor1.timerflags.adc_readings_ready_tic) process_currents(&Motor1, &Motor2); + if (Motor1.timerflags.current_loop_tic) CONTROLLER_StateMachine(); } } + + diff --git a/2_Motor_Master/Motor_Master/Motor_Master/motorparameters.h b/2_Motor_Master/Motor_Master/Motor_Master/motorparameters.h index 5027e3d..4dd264a 100644 --- a/2_Motor_Master/Motor_Master/Motor_Master/motorparameters.h +++ b/2_Motor_Master/Motor_Master/Motor_Master/motorparameters.h @@ -10,7 +10,6 @@ #define MOTORPARAMETERS_H_ #include "atmel_start.h" - // ---------------------------------------------------------------------- // M1 Hall Parameters // ---------------------------------------------------------------------- @@ -55,34 +54,6 @@ #define M2_HALL_C_LSR M2_HALL_C_PIN - M2_HALL_C_GROUP*32 -2 #define M2_HALL_C_GROUP M2_HALL_C_PIN/32 -// ---------------------------------------------------------------------- -// Motor Physical Parameters -// ---------------------------------------------------------------------- - -const typedef struct -{ - const uint16_t Poles; - const uint16_t polePairs; - const uint16_t commutationStates; - const float32_t motor_RS_Ohm; - const float32_t motor_LD_H; - const float32_t motor_Flux_WB; - const float32_t motor_Max_Spd_RPM; - const float32_t motor_Max_Spd_ELEC; - const float32_t motor_MeasureRange_RPM; // give 20% headroom - const float32_t motor_Max_Current_IDC_A; -} BLDCMotor_param_t; - -const BLDCMotor_param_t FH_32mm24BXTR = { - .Poles = 14, - .polePairs = 7, - .commutationStates = 42, //polePairs * 6 - -}; -const BLDCMotor_param_t FH_22mm24BXTR; - - - /* ---------------------------------------------------------------------- // Commutation Patterns // ---------------------------------------------------------------------- @@ -98,23 +69,117 @@ const BLDCMotor_param_t FH_22mm24BXTR; ** W7 | M1_0 | CC0 || M2_0 | CC0 | */ -static const uint16_t COMMUTATION_PATTERN[] = { +static const uint16_t COMMUTATION_PATTERN[16] = { 0x00FF, // (0) invalid state - 0x30F8, // (1) - 0x50F5, // (2) - 0x60F8, // (3) - 0x607D, // (4) - 0x507D, // (5) - 0x30F5, // (6) + 0x303B, // (1) + 0x183D, // (2) + 0x283B, // (3) + 0x283E, // (4) + 0x183E, // (5) + 0x303D, // (6) 0x00FF, // (7) invalid state 0x00FF, // (8) invalid state - 0x30F5, // (9) - 0x507D, // (10) - 0x607D, // (11) - 0x60F8, // (12) - 0x50F5, // (13) - 0x30F8, // (14) + 0x303D, // (9) + 0x183E, // (10) + 0x283E, // (11) + 0x283B, // (12) + 0x183D, // (13) + 0x303B, // (14) 0x00FF // (15) invalid state }; +typedef struct +{ + uint8_t hallA; + uint8_t hallB; + uint8_t hallC; +} Hall_pins_t; + +// ---------------------------------------------------------------------- +// Motor Physical Parameters +// ---------------------------------------------------------------------- +typedef struct +{ + struct pwm_descriptor const *pwm_desc; + const uint16_t motor_Poles; + const uint16_t motor_polePairs; + const uint16_t motor_commutationStates; + const float32_t motor_RS_Ohm; + const float32_t motor_LD_H; + const float32_t motor_LQ_H; + const float32_t motor_Flux_WB; + const float32_t motor_Max_Spd_RPM; + const float32_t motor_MeasureRange_RPM; // give 20% headroom + const float32_t motor_Max_Spd_ELEC; + const float32_t motor_Max_Current_IDC_A; + const Hall_pins_t hallPins; +} BLDCMotor_param_t; + +//static BLDCMotor_param_t FH_22mm24BXTR; +//static BLDCMotor_param_t FH_32mm24BXTR; + +/* Small Motor - 2214S024BXTR*/ +const static BLDCMotor_param_t FH_22mm24BXTR = { + .pwm_desc = &PWM_0, + .motor_Poles = 14, + .motor_polePairs = 7, + .motor_commutationStates = 42, //polePairs * 6 + .motor_RS_Ohm = 25.9, + .motor_LD_H = 0.003150, + .motor_LQ_H = 0.003150, + .motor_Flux_WB = 0.001575, + .motor_Max_Spd_RPM = 3000, + .motor_MeasureRange_RPM = 3000 * 1.2, //(1.2f * MOTOR_MAX_SPD_RPM)f // give 20% headroom + .motor_Max_Spd_ELEC = (3000/60)*7.0, //(MOTOR_MAX_SPD_RPM/60)*MOTOR_POLEPAIRS + .motor_Max_Current_IDC_A = 0.368, + .hallPins = {M1_HALL_A_PIN, M1_HALL_B_PIN, M1_HALL_C_PIN} + +}; + +/* Big Motor - 3216W024BXTR */ +const static BLDCMotor_param_t FH_32mm24BXTR = { + .pwm_desc = &PWM_1, + .motor_Poles = 14, + .motor_polePairs = 7, + .motor_commutationStates = 42, //polePairs * 6 + .motor_RS_Ohm = 3.37, + .motor_LD_H = 0.001290, + .motor_LQ_H = 0.001290, + .motor_Flux_WB = 0.0063879968, + .motor_Max_Spd_RPM = 3000, + .motor_MeasureRange_RPM = 3200, //(1.2f * MOTOR_MAX_SPD_RPM)f // give 20% headroom + .motor_Max_Spd_ELEC = 12000, //(MOTOR_MAX_SPD_RPM/60)*MOTOR_POLEPAIRS + .motor_Max_Current_IDC_A = 1.2, +}; + + +//static void initMotorParameters(void) +//{ + //FH_22mm24BXTR.pwm_desc = &PWM_0; + //FH_22mm24BXTR.motor_Poles = 14; + //FH_22mm24BXTR.motor_polePairs = 7; + //FH_22mm24BXTR.motor_commutationStates = 42; //polePairs * 6 + //FH_22mm24BXTR.motor_RS_Ohm = 25.9; + //FH_22mm24BXTR.motor_LD_H = 0.003150; + //FH_22mm24BXTR.motor_LQ_H = 0.003150; + //FH_22mm24BXTR.motor_Flux_WB = 0.001575; + //FH_22mm24BXTR.motor_Max_Spd_RPM = 3000; + //FH_22mm24BXTR.motor_MeasureRange_RPM = 3000 * 1.2; //(1.2f * MOTOR_MAX_SPD_RPM)f // give 20% headroom + //FH_22mm24BXTR.motor_Max_Spd_ELEC = (3000/60)*7.0; //(MOTOR_MAX_SPD_RPM/60)*MOTOR_POLEPAIRS + //FH_22mm24BXTR.motor_Max_Current_IDC_A = 0.368; + // + //FH_32mm24BXTR.pwm_desc = &PWM_1; + //FH_32mm24BXTR.motor_Poles = 14; + //FH_32mm24BXTR.motor_polePairs = 7; + //FH_32mm24BXTR.motor_commutationStates = 42; //polePairs * 6 + //FH_32mm24BXTR.motor_RS_Ohm = 3.37; + //FH_32mm24BXTR.motor_LD_H = 0.001290; + //FH_32mm24BXTR.motor_LQ_H = 0.001290; + //FH_32mm24BXTR.motor_Flux_WB = 0.0063879968; + //FH_32mm24BXTR.motor_Max_Spd_RPM = 3000; + //FH_32mm24BXTR.motor_MeasureRange_RPM = 3200; //(1.2f * MOTOR_MAX_SPD_RPM)f // give 20% headroom + //FH_32mm24BXTR.motor_Max_Spd_ELEC = 12000; //(MOTOR_MAX_SPD_RPM/60)*MOTOR_POLEPAIRS + //FH_32mm24BXTR.motor_Max_Current_IDC_A = 1.2; +//} + #endif /* MOTORPARAMETERS_H_ */ \ No newline at end of file diff --git a/2_Motor_Master/Motor_Master/Motor_Master/statemachine.h b/2_Motor_Master/Motor_Master/Motor_Master/statemachine.h new file mode 100644 index 0000000..3e8ec7c --- /dev/null +++ b/2_Motor_Master/Motor_Master/Motor_Master/statemachine.h @@ -0,0 +1,50 @@ +/* + * statemachine.h + * + * Created: 05/04/2021 13:23:24 + * Author: Nick-XMG + */ + + +#ifndef STATEMACHINE_H_ +#define STATEMACHINE_H_ + + +typedef enum +{ + SYSTEM_INIT = 0, + SYSTEM_IDLE = 1, + MOTOR_IDLE = 2, + MOTOR_I_CTRL_STATE = 3, + MOTOR_V_CTRL_STATE = 4, + MOTOR_P_CTRL_STATE = 5, + MOTOR_VI_CTRL_STATE = 6, + MOTOR_PVI_CTRL_STATE = 7, + MOTOR_STOP = 8, + FAULT = 9, + COMMSTEST = 10, + MOTOR_OPEN_LOOP_STATE = 11 +} CONTROLLER_FSM; + +typedef enum +{ + NOFAULT = 0, + VOLTAGE = 1, + OVERCURRENT = 2, + OVERTEMPERATURE = 3, + MOTOR_STALL = 4, + HALLSENSORINVALID = 5, + GATE_DRIVER = 6, + UNKNOWN = 7 +} FAULTS; + +typedef struct APPLICATION_STATUS +{ + CONTROLLER_FSM currentstate; + CONTROLLER_FSM previousstate; + FAULTS fault; +} APPLICATION_STATUS; + +APPLICATION_STATUS applicationStatus; + +#endif /* STATEMACHINE_H_ */ \ No newline at end of file diff --git a/2_Motor_Master/Motor_Master/Motor_Master/utilities.h b/2_Motor_Master/Motor_Master/Motor_Master/utilities.h new file mode 100644 index 0000000..66cce8b --- /dev/null +++ b/2_Motor_Master/Motor_Master/Motor_Master/utilities.h @@ -0,0 +1,155 @@ +/* + * utilities.h + * + * Created: 20/04/2021 19:59:00 + * Author: Nick-XMG + */ + + +#ifndef UTILITIES_H_ +#define UTILITIES_H_ + + +#define ENABLED(V...) DO(ENA,&&,V) +#define DISABLED(V...) DO(DIS,&&,V) +#include "arm_math.h" + +#define DEBUG_1_PORT PORT_PC01 +#define DEBUG_2_PORT PORT_PC03 +#define DEBUG_3_PORT PORT_PC02 +#define DEBUG_4_PORT PORT_PC30 + +static inline void tic(const uint8_t pin) +{ + gpio_set_pin_level(pin, true); +} + +static inline void toc(const uint8_t pin) +{ + gpio_set_pin_level(pin, false); +} + +static inline void tic_port(const uint32_t port) +{ + REG_PORT_OUTSET2 = port; +} + +static inline void toc_port(const uint32_t port) +{ + REG_PORT_OUTCLR2 = port; +} + +//! \brief Saturates the input value between the minimum and maximum values +//! \param[in] in The input value +//! \param[in] max The maximum value allowed +//! \param[in] min The minimum value allowed +//! \return The saturated value +static inline float32_t f_clamp(const float32_t in, const float32_t min, const float32_t max) +{ + float32_t out = in; + + + if(in < min) + { + out = min; + } + else if(in > max) + { + out = max; + } + else + { + // do nothing as of now + ; + } + + return(out); +} + +//! \brief Finds the absolute value +//! \param[in] in The input value +//! \return The absolute value +static inline float32_t f_abs(const float32_t in) +{ + float32_t out = in; + if(in < (float32_t)0.0) + { + out = -in; + } + + return(out); +} + +// the typedefs + +//! \brief Defines the first-order filter (FILTER_FO) object +//! +typedef struct _FILTER_FO_Obj_ +{ + float32_t a1; //the denominator filter coefficient value for z^(-1) + + float32_t b0; //the numerator filter coefficient value for z^0 + float32_t b1; //the numerator filter coefficient value for z^(-1) + + float32_t x1; //the input value at time sample n=-1 + + float32_t y1; //the output value at time sample n=-1 +} FILTER_FO_Obj; + + +//! \brief Runs a first-order filter of the form +//! y[n] = b0*x[n] + b1*x[n-1] - a1*y[n-1] +//! +//! \param[in] handle The filter handle +//! \param[in] inputValue The input value to filter +//! \return The output value from the filter + +static inline float32_t FILTER_FO_run(volatile FILTER_FO_Obj *handle, const float32_t inputValue) +{ + FILTER_FO_Obj *obj = (FILTER_FO_Obj *)handle; + + float32_t a1 = obj->a1; + float32_t b0 = obj->b0; + float32_t b1 = obj->b1; + float32_t x1 = obj->x1; + float32_t y1 = obj->y1; + + + // compute the output + float32_t y0 = (b0 * inputValue) + (b1 * x1) - (a1 * y1); + + + // store values for next time + obj->x1 = inputValue; + obj->y1 = y0; + + return(y0); +} // end of FILTER_FO_run() function + + +//! \brief Runs a first-order filter of the form +//! y[n] = b0*x[n] - a1*y[n-1] +//! +//! \param[in] handle The filter handle +//! \param[in] inputValue The input value to filter +//! \return The output value from the filter +static inline float32_t FILTER_FO_run_form_0(volatile FILTER_FO_Obj *handle, const float32_t inputValue) +{ + FILTER_FO_Obj *obj = (FILTER_FO_Obj *)handle; + + float32_t a1 = obj->a1; + float32_t b0 = obj->b0; + float32_t y1 = obj->y1; + + + // compute the output + float32_t y0 = (b0 * inputValue) - (a1 * y1); + + + // store values for next time + obj->y1 = y0; + + return(y0); +} // end of FILTER_FO_run_form_0() function + +#endif /* UTILITIES_H_ */ \ No newline at end of file