Change control algorithm for ParameterID#

The ParameterID does not have its own control algorithm. This is done externally, as shown in Fig. 287. The ParameterID is based on functions from the CurrentControl and Speed Control module. If changing the used controller is desired, these functions must be adjusted.

Following is the code of the function uz_ParameterID_Controller, with the function calls to uz_FOC and uz_SpeedController removed. This can be used as a template to include your new controller.

Listing 120 template code to include your own controller#
 1uz_3ph_dq_t uz_ParameterID_Controller(uz_ParameterID_Data_t* Data, uz_CurrentControl_t* CC_instance, uz_SpeedControl_t* SC_instance, uz_SetPoint_t* SP_instance) {
 2  uz_assert_not_NULL(Data);
 3  uz_assert_not_NULL(CC_instance);
 4  uz_assert_not_NULL(SC_instance);
 5  uz_assert_not_NULL(SP_instance);
 6  uz_3ph_dq_t v_dq_Volts = { 0 };
 7  uz_3ph_dq_t i_SpeedControl_reference_Ampere = { 0 };
 8  float SpeedControl_reference_torque = 0.0f;
 9
10  if (Data->Controller_Parameters.enableFOC_speed) {
11    //Add your speed controller here. Should output reference-dq-currents in the uz_3ph_dq_t system or a reference-torque for a subsequent setpoint module.
12    //In the latter case, the setpoint module has to output the reference dq-currents.
13    i_SpeedControl_reference_Ampere = ....
14    //ADD PRBS excitation for TwoMassID
15    i_SpeedControl_reference_Ampere.q += Data->TwoMassID_Output->PRBS_out;
16  }
17  if (Data->Controller_Parameters.enableFOC_torque) {
18    //Add your setpoint module here, which calculates dq-currents based on a reference torque.
19    i_SpeedControl_reference_Ampere = ....
20  }
21  if (Data->Controller_Parameters.enableFOC_current || Data->Controller_Parameters.enableFOC_speed || Data->Controller_Parameters.enableFOC_torque) {
22    //Add your current controller here. Should output dq-currents in the uz_3ph_dq_t system
23    if (Data->Controller_Parameters.enableFOC_current) {
24      //If CurrentControl is active, use Data->Controller_Parameters.i_dq_ref as input reference currents
25      v_dq_Volts = ....
26    } else if (Data->Controller_Parameters.enableFOC_torque || Data->Controller_Parameters.enableFOC_speed)  {
27      //If SpeedControl or TorqueControl is active, use i_SpeedControl_reference_Ampere as input reference currents.
28      //The controller should output reference voltages for the SVM in the dq-plane.
29      v_dq_Volts = ....
30    }
31  }
32  if (Data->Controller_Parameters.resetIntegrator) {
33    //Reset integrators, if necessary
34    ....
35  }
36  if (Data->ControlFlags->transNr > 0U && Data->ControlFlags->transNr <= 4U) {
37    if (Data->Controller_Parameters.activeState == 144U) {
38      //Change decoupling method, if needed
39      ....
40    } else if (Data->Controller_Parameters.activeState == 170U) {
41      //Change decoupling method, if needed
42      ....
43    }
44    //During identification, if a FOC is used, update the control parameters (Kp,Ki) here
45    ....
46  }
47  //This is the setup for the Controller for Online-ID-states
48  if (Data->ControlFlags->finished_all_Offline_states) {
49    uz_3ph_dq_t Online_current_ref = {0};
50    if (Data->ParaID_Control_Selection == Current_Control || Data->ParaID_Control_Selection == Speed_Control || Data->ParaID_Control_Selection == Torque_Control) {
51      if (Data->ParaID_Control_Selection == Speed_Control) {
52        //Add your speedcontroller here. Should output reference-dq-currents in the uz_3ph_dq_t system or a reference-torque for a subsequent setpoint module.
53        //In the later case the setpoint module has to output the reference dq-currents.
54        Online_current_ref = ....
55      } else if (Data->ParaID_Control_Selection == Torque_Control) {
56        //Add your setpoint module here which calculates dq-currents based on a reference torque.
57        Online_current_ref = ....
58      } else {
59        //Use the manual reference currents
60        Online_current_ref = Data->GlobalConfig.i_dq_ref;
61      }
62    }
63    if (Data->OnlineID_Output->IdControlFlag == true) {
64      if (Data->AutoRefCurrents_Config.enableCRS == true && Data->ParaID_Control_Selection == Current_Control) {//Overwrite dq-ref-currents when AutoRefCurrents is active
65        Online_current_ref.d = Data->OnlineID_Output->id_out + Data->AutoRefCurrents_Output.i_dq_ref.d;
66        Online_current_ref.q = Data->AutoRefCurrents_Output.i_dq_ref.q;
67      } else {
68        Online_current_ref.d = Data->GlobalConfig.i_dq_ref.d + Data->OnlineID_Output->id_out;
69      }
70    } else {
71      if (Data->AutoRefCurrents_Config.enableCRS == true && Data->ParaID_Control_Selection == Current_Control) {
72        Online_current_ref.d = Data->AutoRefCurrents_Output.i_dq_ref.d;
73        Online_current_ref.q = Data->AutoRefCurrents_Output.i_dq_ref.q;
74      }
75    }
76    //Add your CurrentController here. The controller should output reference voltages for the SVM in the dq-plane.
77    v_dq_Volts = ....
78  }
79  return (v_dq_Volts);
80}

The function uz_ParameterID_generate_DutyCycle, can be adjusted as well. It uses a continuous sinusoidal PWM (SPWM) modulation from blank to generate the DutyCycles.

Listing 121 template code to generate DutyCycles#
 1struct uz_DutyCycle_t uz_ParameterID_generate_DutyCycle(uz_ParameterID_Data_t* Data, uz_3ph_dq_t v_dq_Volts, uz_PWM_SS_2L_t* PWM_Module) {
 2  uz_assert_not_NULL(Data);
 3  uz_assert_not_NULL(PWM_Module);
 4  struct uz_DutyCycle_t output_DutyCycle = { 0 };
 5  if (Data->Controller_Parameters.activeState >= 110 && Data->Controller_Parameters.activeState <= 143) {
 6    uz_PWM_SS_2L_set_tristate(PWM_Module, Data->ElectricalID_Output->enable_TriState[0], Data->ElectricalID_Output->enable_TriState[1], Data->ElectricalID_Output->enable_TriState[2]);
 7    output_DutyCycle.DutyCycle_U = Data->ElectricalID_Output->PWM_Switch_0;
 8    output_DutyCycle.DutyCycle_V = Data->ElectricalID_Output->PWM_Switch_2;
 9    output_DutyCycle.DutyCycle_W = Data->ElectricalID_Output->PWM_Switch_4;
10  } else if ((Data->Controller_Parameters.enableFOC_current || Data->Controller_Parameters.enableFOC_speed || Data->Controller_Parameters.enableFOC_torque)
11                || (Data->ControlFlags->finished_all_Offline_states && (Data->ParaID_Control_Selection == Current_Control || Data->ParaID_Control_Selection == Speed_Control || Data->ParaID_Control_Selection == Torque_Control))) {
12    //Use your own function to generate DutyCycles here, if the control algorithms are used
13    output_DutyCycle = ....
14  } else {
15    output_DutyCycle.DutyCycle_U = 0.0f;
16    output_DutyCycle.DutyCycle_V = 0.0f;
17    output_DutyCycle.DutyCycle_W = 0.0f;
18  }
19  if (Data->Controller_Parameters.resetIntegrator) {
20    output_DutyCycle.DutyCycle_U = 0.0f;
21    output_DutyCycle.DutyCycle_V = 0.0f;
22    output_DutyCycle.DutyCycle_W = 0.0f;
23  }
24return (output_DutyCycle);
25}