From b76e8ee4666ec5e0a017150bdb8545cffed99ddf Mon Sep 17 00:00:00 2001 From: EmanuelFeru Date: Mon, 12 Oct 2020 22:55:39 +0200 Subject: [PATCH] Update BLDC controller - added possbility to switch the Control mode while motor is spinning. NOT yet checked how motors behaves when swiching is triggered! - added Cruise Control functionality: activated by button1 to GND (Blue Left or Right cable depending on selection). Functionality NOT yet tested in practice! - extended Phase current measurements z_selPhaCurMeasABC : {iA,iB} = 0; {iB,iC} = 1; {iA,iC} = 2 - added interface for external motor angle measurement from as sensor, e.g., encoder. The selection can be done via b_angleMeasEna: 0 = Estimated (default), 1 = Measured. - update the Field weakening Lo and Hi to fully blended. - minor improvements: - Buttons initialization - lowered ADC margins in auto-calibration - commented out ADC_SAMPLETIME_239CYCLES_5, reported to give some issues when Hall sensor ADC input is used --- Inc/BLDC_controller.h | 445 +++---- Inc/config.h | 27 +- Inc/rtwtypes.h | 4 +- README.md | 4 +- Src/BLDC_controller.c | 2253 +++++++++++++++++++++------------- Src/BLDC_controller_data.c | 114 +- Src/bldc.c | 6 +- Src/setup.c | 12 +- Src/util.c | 40 +- docs/pictures/paramTable.png | Bin 63028 -> 0 bytes 10 files changed, 1785 insertions(+), 1120 deletions(-) delete mode 100644 docs/pictures/paramTable.png diff --git a/Inc/BLDC_controller.h b/Inc/BLDC_controller.h index d7a2841..264222a 100644 --- a/Inc/BLDC_controller.h +++ b/Inc/BLDC_controller.h @@ -3,9 +3,9 @@ * * Code generated for Simulink model 'BLDC_controller'. * - * Model version : 1.1260 + * Model version : 1.1284 * Simulink Coder version : 8.13 (R2017b) 24-Jul-2017 - * C/C++ source code generated on : Tue Mar 24 11:01:08 2020 + * C/C++ source code generated on : Sun Oct 11 21:38:56 2020 * * Target selection: ert.tlc * Embedded hardware selection: ARM Compatible->ARM Cortex @@ -32,82 +32,97 @@ typedef struct tag_RTM RT_MODEL; /* Block signals and states (auto storage) for system '/Counter' */ typedef struct { - int16_T UnitDelay_DSTATE; /* '/UnitDelay' */ + int16_T UnitDelay_DSTATE; /* '/UnitDelay' */ } DW_Counter; -/* Block signals and states (auto storage) for system '/PI_clamp_fixdt' */ +/* Block signals and states (auto storage) for system '/PI_clamp_fixdt' */ typedef struct { - int32_T UnitDelay_DSTATE; /* '/UnitDelay' */ - boolean_T UnitDelay1_DSTATE; /* '/UnitDelay1' */ + int32_T ResettableDelay_DSTATE; /* '/Resettable Delay' */ + uint8_T icLoad; /* '/Resettable Delay' */ + boolean_T UnitDelay1_DSTATE; /* '/UnitDelay1' */ } DW_PI_clamp_fixdt; -/* Block signals and states (auto storage) for system '/Low_Pass_Filter' */ +/* Block signals and states (auto storage) for system '/PI_clamp_fixdt' */ typedef struct { - int32_T UnitDelay1_DSTATE[2]; /* '/UnitDelay1' */ + int32_T ResettableDelay_DSTATE; /* '/Resettable Delay' */ + uint8_T icLoad; /* '/Resettable Delay' */ + boolean_T UnitDelay1_DSTATE; /* '/UnitDelay1' */ +} DW_PI_clamp_fixdt_i; + +/* Block signals and states (auto storage) for system '/PI_clamp_fixdt' */ +typedef struct { + int16_T ResettableDelay_DSTATE; /* '/Resettable Delay' */ + uint8_T icLoad; /* '/Resettable Delay' */ + boolean_T UnitDelay1_DSTATE; /* '/UnitDelay1' */ +} DW_PI_clamp_fixdt_e; + +/* Block signals and states (auto storage) for system '/Low_Pass_Filter' */ +typedef struct { + int32_T UnitDelay1_DSTATE[2]; /* '/UnitDelay1' */ } DW_Low_Pass_Filter; -/* Block signals and states (auto storage) for system '/I_backCalc_fixdt' */ +/* Block signals and states (auto storage) for system '/I_backCalc_fixdt' */ typedef struct { - int32_T UnitDelay_DSTATE; /* '/UnitDelay' */ - int32_T UnitDelay_DSTATE_h; /* '/UnitDelay' */ + int32_T UnitDelay_DSTATE; /* '/UnitDelay' */ + int32_T UnitDelay_DSTATE_h; /* '/UnitDelay' */ } DW_I_backCalc_fixdt; -/* Block signals and states (auto storage) for system '/Counter' */ +/* Block signals and states (auto storage) for system '/Counter' */ typedef struct { - uint16_T UnitDelay_DSTATE; /* '/UnitDelay' */ + uint16_T UnitDelay_DSTATE; /* '/UnitDelay' */ } DW_Counter_l; -/* Block signals and states (auto storage) for system '/either_edge' */ +/* Block signals and states (auto storage) for system '/either_edge' */ typedef struct { - boolean_T UnitDelay_DSTATE; /* '/UnitDelay' */ + boolean_T UnitDelay_DSTATE; /* '/UnitDelay' */ } DW_either_edge; /* Block signals and states (auto storage) for system '/Debounce_Filter' */ typedef struct { - DW_either_edge either_edge_k; /* '/either_edge' */ - DW_Counter_l Counter_h; /* '/Counter' */ - DW_Counter_l Counter_i0; /* '/Counter' */ - boolean_T UnitDelay_DSTATE; /* '/UnitDelay' */ + DW_either_edge either_edge_k; /* '/either_edge' */ + DW_Counter_l Counter_h; /* '/Counter' */ + DW_Counter_l Counter_i0; /* '/Counter' */ + boolean_T UnitDelay_DSTATE; /* '/UnitDelay' */ } DW_Debounce_Filter; /* Block signals and states (auto storage) for system '' */ typedef struct { DW_either_edge either_edge_a; /* '/either_edge' */ DW_Debounce_Filter Debounce_Filter_f;/* '/Debounce_Filter' */ - DW_I_backCalc_fixdt I_backCalc_fixdt_g;/* '/I_backCalc_fixdt' */ - DW_I_backCalc_fixdt I_backCalc_fixdt1;/* '/I_backCalc_fixdt1' */ - DW_I_backCalc_fixdt I_backCalc_fixdt_i;/* '/I_backCalc_fixdt' */ - DW_Low_Pass_Filter Low_Pass_Filter_m;/* '/Low_Pass_Filter' */ - DW_PI_clamp_fixdt PI_clamp_fixdt_a; /* '/PI_clamp_fixdt' */ - DW_PI_clamp_fixdt PI_clamp_fixdt_o; /* '/PI_clamp_fixdt' */ - DW_PI_clamp_fixdt PI_clamp_fixdt_k; /* '/PI_clamp_fixdt' */ + DW_I_backCalc_fixdt I_backCalc_fixdt_g;/* '/I_backCalc_fixdt' */ + DW_I_backCalc_fixdt I_backCalc_fixdt1;/* '/I_backCalc_fixdt1' */ + DW_I_backCalc_fixdt I_backCalc_fixdt_i;/* '/I_backCalc_fixdt' */ + DW_Low_Pass_Filter Low_Pass_Filter_m;/* '/Low_Pass_Filter' */ + DW_PI_clamp_fixdt_e PI_clamp_fixdt_at;/* '/PI_clamp_fixdt' */ + DW_PI_clamp_fixdt_i PI_clamp_fixdt_oc;/* '/PI_clamp_fixdt' */ + DW_PI_clamp_fixdt PI_clamp_fixdt_k; /* '/PI_clamp_fixdt' */ DW_Counter Counter_e; /* '/Counter' */ - int32_T Divide1; /* '/Divide1' */ - int32_T UnitDelay_DSTATE; /* '/UnitDelay' */ - int16_T Gain4[3]; /* '/Gain4' */ - int16_T DataTypeConversion[2]; /* '/Data Type Conversion' */ - int16_T z_counterRawPrev; /* '/z_counterRawPrev' */ - int16_T Merge1; /* '/Merge1' */ + int32_T Divide1; /* '/Divide1' */ + int32_T UnitDelay_DSTATE; /* '/UnitDelay' */ + int16_T Gain4[3]; /* '/Gain4' */ + int16_T DataTypeConversion[2]; /* '/Data Type Conversion' */ + int16_T z_counterRawPrev; /* '/z_counterRawPrev' */ + int16_T Merge1; /* '/Merge1' */ int16_T Divide3; /* '/Divide3' */ - int16_T Vd_max1; /* '/Vd_max1' */ - int16_T Gain3; /* '/Gain3' */ - int16_T Vq_max_M1; /* '/Vq_max_M1' */ - int16_T Gain5; /* '/Gain5' */ - int16_T i_max; /* '/i_max' */ - int16_T Divide1_a; /* '/Divide1' */ - int16_T Gain1; /* '/Gain1' */ - int16_T Gain4_c; /* '/Gain4' */ - int16_T Switch2; /* '/Switch2' */ - int16_T Switch2_l; /* '/Switch2' */ - int16_T Switch2_c; /* '/Switch2' */ - int16_T Merge; /* '/Merge' */ - int16_T Switch1; /* '/Switch1' */ - int16_T Divide11; /* '/Divide11' */ + int16_T Vd_max1; /* '/Vd_max1' */ + int16_T Gain3; /* '/Gain3' */ + int16_T Vq_max_M1; /* '/Vq_max_M1' */ + int16_T Gain5; /* '/Gain5' */ + int16_T i_max; /* '/i_max' */ + int16_T Divide1_a; /* '/Divide1' */ + int16_T Gain1; /* '/Gain1' */ + int16_T Gain4_c; /* '/Gain4' */ + int16_T Switch2; /* '/Switch2' */ + int16_T Switch2_l; /* '/Switch2' */ + int16_T Switch2_c; /* '/Switch2' */ + int16_T Merge; /* '/Merge' */ + int16_T Switch1; /* '/Switch1' */ + int16_T Divide11; /* '/Divide11' */ int16_T UnitDelay3_DSTATE; /* '/UnitDelay3' */ - int16_T UnitDelay4_DSTATE; /* '/UnitDelay4' */ - int16_T UnitDelay2_DSTATE; /* '/UnitDelay2' */ - int16_T UnitDelay3_DSTATE_o; /* '/UnitDelay3' */ - int16_T UnitDelay5_DSTATE; /* '/UnitDelay5' */ + int16_T UnitDelay4_DSTATE; /* '/UnitDelay4' */ + int16_T UnitDelay2_DSTATE; /* '/UnitDelay2' */ + int16_T UnitDelay3_DSTATE_o; /* '/UnitDelay3' */ + int16_T UnitDelay5_DSTATE; /* '/UnitDelay5' */ int16_T UnitDelay4_DSTATE_e; /* '/UnitDelay4' */ int16_T UnitDelay4_DSTATE_eu; /* '/UnitDelay4' */ int16_T UnitDelay4_DSTATE_h; /* '/UnitDelay4' */ @@ -115,8 +130,10 @@ typedef struct { int8_T UnitDelay2_DSTATE_b; /* '/UnitDelay2' */ int8_T If4_ActiveSubsystem; /* '/If4' */ int8_T If1_ActiveSubsystem; /* '/If1' */ - int8_T If2_ActiveSubsystem; /* '/If2' */ + int8_T If2_ActiveSubsystem; /* '/If2' */ int8_T If2_ActiveSubsystem_a; /* '/If2' */ + int8_T If1_ActiveSubsystem_e; /* '/If1' */ + int8_T SwitchCase_ActiveSubsystem; /* '/Switch Case' */ uint8_T z_ctrlMod; /* '/F03_02_Control_Mode_Manager' */ uint8_T UnitDelay3_DSTATE_fy; /* '/UnitDelay3' */ uint8_T UnitDelay1_DSTATE; /* '/UnitDelay1' */ @@ -124,51 +141,51 @@ typedef struct { uint8_T is_active_c1_BLDC_controller;/* '/F03_02_Control_Mode_Manager' */ uint8_T is_c1_BLDC_controller; /* '/F03_02_Control_Mode_Manager' */ uint8_T is_ACTIVE; /* '/F03_02_Control_Mode_Manager' */ - boolean_T Merge_n; /* '/Merge' */ - boolean_T dz_cntTrnsDet; /* '/dz_cntTrnsDet' */ + boolean_T Merge_n; /* '/Merge' */ + boolean_T dz_cntTrnsDet; /* '/dz_cntTrnsDet' */ boolean_T UnitDelay2_DSTATE_g; /* '/UnitDelay2' */ boolean_T UnitDelay5_DSTATE_l; /* '/UnitDelay5' */ boolean_T UnitDelay6_DSTATE; /* '/UnitDelay6' */ - boolean_T UnitDelay_DSTATE_e; /* '/UnitDelay' */ - boolean_T UnitDelay1_DSTATE_n; /* '/UnitDelay1' */ + boolean_T UnitDelay_DSTATE_b; /* '/UnitDelay' */ + boolean_T UnitDelay1_DSTATE_n; /* '/UnitDelay1' */ boolean_T n_commDeacv_Mode; /* '/n_commDeacv' */ - boolean_T dz_cntTrnsDet_Mode; /* '/dz_cntTrnsDet' */ + boolean_T dz_cntTrnsDet_Mode; /* '/dz_cntTrnsDet' */ } DW; /* Constant parameters (auto storage) */ typedef struct { /* Computed Parameter: r_sin3PhaA_M1_Table - * Referenced by: '/r_sin3PhaA_M1' + * Referenced by: '/r_sin3PhaA_M1' */ int16_T r_sin3PhaA_M1_Table[181]; /* Computed Parameter: r_sin3PhaB_M1_Table - * Referenced by: '/r_sin3PhaB_M1' + * Referenced by: '/r_sin3PhaB_M1' */ int16_T r_sin3PhaB_M1_Table[181]; /* Computed Parameter: r_sin3PhaC_M1_Table - * Referenced by: '/r_sin3PhaC_M1' + * Referenced by: '/r_sin3PhaC_M1' */ int16_T r_sin3PhaC_M1_Table[181]; /* Computed Parameter: r_sin_M1_Table - * Referenced by: '/r_sin_M1' + * Referenced by: '/r_sin_M1' */ int16_T r_sin_M1_Table[181]; /* Computed Parameter: r_cos_M1_Table - * Referenced by: '/r_cos_M1' + * Referenced by: '/r_cos_M1' */ int16_T r_cos_M1_Table[181]; /* Computed Parameter: iq_maxSca_M1_Table - * Referenced by: '/iq_maxSca_M1' + * Referenced by: '/iq_maxSca_M1' */ uint16_T iq_maxSca_M1_Table[50]; /* Computed Parameter: z_commutMap_M1_table - * Referenced by: '/z_commutMap_M1' + * Referenced by: '/z_commutMap_M1' */ int8_T z_commutMap_M1_table[18]; @@ -189,6 +206,7 @@ typedef struct { int16_T i_phaAB; /* '/i_phaAB' */ int16_T i_phaBC; /* '/i_phaBC' */ int16_T i_DCLink; /* '/i_DCLink' */ + int16_T a_mechAngle; /* '/a_mechAngle' */ } ExtU; /* External outputs (root outports fed by signals with auto storage) */ @@ -199,20 +217,23 @@ typedef struct { uint8_T z_errCode; /* '/z_errCode' */ int16_T n_mot; /* '/n_mot' */ int16_T a_elecAngle; /* '/a_elecAngle' */ - int16_T r_devSignal1; /* '/r_devSignal1' */ - int16_T r_devSignal2; /* '/r_devSignal2' */ + int16_T iq; /* '/iq' */ + int16_T id; /* '/id' */ } ExtY; /* Parameters (auto storage) */ struct P_ { int32_T dV_openRate; /* Variable: dV_openRate - * Referenced by: '/dV_openRate' + * Referenced by: '/dV_openRate' */ int16_T dz_cntTrnsDetHi; /* Variable: dz_cntTrnsDetHi - * Referenced by: '/dz_cntTrnsDet' + * Referenced by: '/dz_cntTrnsDet' */ int16_T dz_cntTrnsDetLo; /* Variable: dz_cntTrnsDetLo - * Referenced by: '/dz_cntTrnsDet' + * Referenced by: '/dz_cntTrnsDet' + */ + int16_T n_cruiseMotTgt; /* Variable: n_cruiseMotTgt + * Referenced by: '/n_cruiseMotTgt' */ int16_T z_maxCntRst; /* Variable: z_maxCntRst * Referenced by: @@ -220,10 +241,10 @@ struct P_ { * '/z_maxCntRst' * '/z_maxCntRst2' * '/UnitDelay3' - * '/z_counter' + * '/z_counter' */ uint16_T cf_speedCoef; /* Variable: cf_speedCoef - * Referenced by: '/cf_speedCoef' + * Referenced by: '/cf_speedCoef' */ uint16_T t_errDequal; /* Variable: t_errDequal * Referenced by: '/t_errDequal' @@ -233,22 +254,22 @@ struct P_ { */ int16_T Vd_max; /* Variable: Vd_max * Referenced by: - * '/Vd_max1' - * '/Vd_max' + * '/Vd_max1' + * '/Vd_max' */ int16_T Vq_max_M1[46]; /* Variable: Vq_max_M1 - * Referenced by: '/Vq_max_M1' + * Referenced by: '/Vq_max_M1' */ int16_T Vq_max_XA[46]; /* Variable: Vq_max_XA - * Referenced by: '/Vq_max_XA' + * Referenced by: '/Vq_max_XA' */ int16_T a_phaAdvMax; /* Variable: a_phaAdvMax * Referenced by: '/a_phaAdvMax' */ int16_T i_max; /* Variable: i_max * Referenced by: - * '/i_max' - * '/i_max' + * '/i_max' + * '/i_max' */ int16_T id_fieldWeakMax; /* Variable: id_fieldWeakMax * Referenced by: '/id_fieldWeakMax' @@ -267,8 +288,8 @@ struct P_ { */ int16_T n_max; /* Variable: n_max * Referenced by: - * '/n_max1' - * '/n_max' + * '/n_max1' + * '/n_max' */ int16_T n_stdStillDet; /* Variable: n_stdStillDet * Referenced by: '/n_stdStillDet' @@ -284,42 +305,56 @@ struct P_ { */ uint16_T cf_KbLimProt; /* Variable: cf_KbLimProt * Referenced by: - * '/cf_KbLimProt' - * '/cf_KbLimProt' + * '/cf_KbLimProt' + * '/cf_KbLimProt' */ uint16_T cf_idKp; /* Variable: cf_idKp - * Referenced by: '/cf_idKp1' + * Referenced by: '/cf_idKp1' */ uint16_T cf_iqKp; /* Variable: cf_iqKp - * Referenced by: '/cf_iqKp' + * Referenced by: '/cf_iqKp' */ uint16_T cf_nKp; /* Variable: cf_nKp - * Referenced by: '/cf_nKp' + * Referenced by: '/cf_nKp' */ uint16_T cf_currFilt; /* Variable: cf_currFilt - * Referenced by: '/cf_currFilt' + * Referenced by: '/cf_currFilt' */ uint16_T cf_idKi; /* Variable: cf_idKi - * Referenced by: '/cf_idKi1' + * Referenced by: '/cf_idKi1' */ uint16_T cf_iqKi; /* Variable: cf_iqKi - * Referenced by: '/cf_iqKi' + * Referenced by: '/cf_iqKi' */ uint16_T cf_iqKiLimProt; /* Variable: cf_iqKiLimProt * Referenced by: - * '/cf_iqKiLimProt' - * '/cf_iqKiLimProt' + * '/cf_iqKiLimProt' + * '/cf_iqKiLimProt' */ uint16_T cf_nKi; /* Variable: cf_nKi - * Referenced by: '/cf_nKi' + * Referenced by: '/cf_nKi' */ uint16_T cf_nKiLimProt; /* Variable: cf_nKiLimProt * Referenced by: - * '/cf_nKiLimProt' - * '/cf_nKiLimProt' + * '/cf_nKiLimProt' + * '/cf_nKiLimProt' + */ + uint8_T n_polePairs; /* Variable: n_polePairs + * Referenced by: '/n_polePairs' */ uint8_T z_ctrlTypSel; /* Variable: z_ctrlTypSel - * Referenced by: '/z_ctrlTypSel1' + * Referenced by: '/z_ctrlTypSel' + */ + uint8_T z_selPhaCurMeasABC; /* Variable: z_selPhaCurMeasABC + * Referenced by: '/z_selPhaCurMeasABC' + */ + boolean_T b_angleMeasEna; /* Variable: b_angleMeasEna + * Referenced by: + * '/b_angleMeasEna' + * '/b_angleMeasEna' + */ + boolean_T b_cruiseCtrlEna; /* Variable: b_cruiseCtrlEna + * Referenced by: '/b_cruiseCtrlEna' */ boolean_T b_diagEna; /* Variable: b_diagEna * Referenced by: '/b_diagEna' @@ -327,10 +362,7 @@ struct P_ { boolean_T b_fieldWeakEna; /* Variable: b_fieldWeakEna * Referenced by: * '/b_fieldWeakEna' - * '/b_fieldWeakEna' - */ - boolean_T b_selPhaABCurrMeas; /* Variable: b_selPhaABCurrMeas - * Referenced by: '/b_selPhaABCurrMeas' + * '/b_fieldWeakEna' */ }; @@ -357,30 +389,30 @@ extern void BLDC_controller_step(RT_MODEL *const rtM); * * Block '/Scope2' : Unused code path elimination * Block '/Scope' : Unused code path elimination - * Block '/Data Type Duplicate' : Unused code path elimination - * Block '/Data Type Propagation' : Unused code path elimination - * Block '/Data Type Duplicate' : Unused code path elimination - * Block '/Data Type Propagation' : Unused code path elimination * Block '/Data Type Duplicate' : Unused code path elimination * Block '/Data Type Propagation' : Unused code path elimination - * Block '/Data Type Duplicate' : Unused code path elimination - * Block '/Data Type Propagation' : Unused code path elimination - * Block '/Data Type Duplicate' : Unused code path elimination - * Block '/Data Type Propagation' : Unused code path elimination - * Block '/Data Type Duplicate' : Unused code path elimination - * Block '/Data Type Propagation' : Unused code path elimination - * Block '/Data Type Duplicate' : Unused code path elimination - * Block '/Data Type Propagation' : Unused code path elimination + * Block '/Data Type Duplicate' : Unused code path elimination + * Block '/Data Type Propagation' : Unused code path elimination + * Block '/Data Type Duplicate' : Unused code path elimination + * Block '/Data Type Propagation' : Unused code path elimination + * Block '/Data Type Duplicate' : Unused code path elimination + * Block '/Data Type Propagation' : Unused code path elimination + * Block '/Data Type Duplicate' : Unused code path elimination + * Block '/Data Type Propagation' : Unused code path elimination + * Block '/Data Type Duplicate' : Unused code path elimination + * Block '/Data Type Propagation' : Unused code path elimination * Block '/Data Type Duplicate' : Unused code path elimination * Block '/Data Type Propagation' : Unused code path elimination - * Block '/Data Type Duplicate' : Unused code path elimination - * Block '/Data Type Propagation' : Unused code path elimination - * Block '/Data Type Duplicate' : Unused code path elimination - * Block '/Data Type Propagation' : Unused code path elimination + * Block '/Data Type Duplicate' : Unused code path elimination + * Block '/Data Type Propagation' : Unused code path elimination + * Block '/Data Type Duplicate' : Unused code path elimination + * Block '/Data Type Propagation' : Unused code path elimination + * Block '/Data Type Duplicate' : Unused code path elimination + * Block '/Data Type Propagation' : Unused code path elimination * Block '/Scope12' : Unused code path elimination * Block '/Scope8' : Unused code path elimination - * Block '/Scope9' : Unused code path elimination - * Block '/Scope' : Unused code path elimination + * Block '/Scope' : Unused code path elimination + * Block '/Data Type Conversion1' : Eliminate redundant data type conversion * Block '/Data Type Conversion' : Eliminate redundant data type conversion */ @@ -396,100 +428,103 @@ extern void BLDC_controller_step(RT_MODEL *const rtM); * MATLAB hilite_system command to trace the generated code back * to the parent model. For example, * - * hilite_system('BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller') - opens subsystem BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller - * hilite_system('BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/Kp') - opens and selects block Kp + * hilite_system('BLDCmotor_FOC_R2017b_fixdt/BLDC_controller') - opens subsystem BLDCmotor_FOC_R2017b_fixdt/BLDC_controller + * hilite_system('BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/Kp') - opens and selects block Kp * * Here is the system hierarchy for this model * - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F04_Field_Weakening' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F06_Control_Type_Management' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/Task_Scheduler' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_01_Edge_Detector' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_02_Position_Calculation' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_03_Direction_Detection' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_04_Speed_Estimation' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_05_Electrical_Angle_Estimation' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_04_Speed_Estimation/Counter' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_04_Speed_Estimation/Raw_Motor_Speed_Estimation' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_04_Speed_Estimation/Counter/rst_Delay' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/either_edge' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Default' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Dequalification' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Qualification' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/either_edge' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Dequalification/Counter' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Dequalification/Counter/rst_Delay' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Qualification/Counter' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Qualification/Counter/rst_Delay' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_01_Mode_Transition_Calculation' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_02_Control_Mode_Manager' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Default_Control_Type' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Default_Mode' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/FOC_Control_Type' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Open_Mode' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Open_Mode/Rate_Limiter' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Open_Mode/rising_edge_init' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Open_Mode/Rate_Limiter/Delay_Init1' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Open_Mode/Rate_Limiter/Saturation Dynamic' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F04_Field_Weakening/Saturation Dynamic' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F04_Field_Weakening/Saturation Dynamic1' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Clarke_Transform' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Current_Filtering' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Inv_Clarke_Transform' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Inv_Park_Transform' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Park_Transform' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Sine_Cosine_Approximation' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Clarke_Transform/Clarke_PhasesAB' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Clarke_Transform/Clarke_PhasesBC' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Current_Filtering/Low_Pass_Filter' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Open_Mode' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Speed_Mode' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Torque_Mode' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Vd_Calculation' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Voltage_Mode' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Speed_Mode/PI_clamp_fixdt' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Speed_Mode/PI_clamp_fixdt/Clamping_circuit' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Speed_Mode/PI_clamp_fixdt/Integrator' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Speed_Mode/PI_clamp_fixdt/Saturation_hit' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Torque_Mode/PI_clamp_fixdt' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Torque_Mode/Saturation Dynamic1' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Torque_Mode/PI_clamp_fixdt/Clamping_circuit' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Torque_Mode/PI_clamp_fixdt/Integrator' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Torque_Mode/PI_clamp_fixdt/Saturation_hit' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Vd_Calculation/PI_clamp_fixdt' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Vd_Calculation/Saturation Dynamic' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Vd_Calculation/PI_clamp_fixdt/Clamping_circuit' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Vd_Calculation/PI_clamp_fixdt/Integrator' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Vd_Calculation/PI_clamp_fixdt/Saturation_hit' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Voltage_Mode/Saturation Dynamic1' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Speed_Mode_Protection' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Torque_Mode_Protection' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Speed_Mode_Protection/Saturation Dynamic' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Torque_Mode_Protection/I_backCalc_fixdt' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Torque_Mode_Protection/I_backCalc_fixdt/Integrator' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Torque_Mode_Protection/I_backCalc_fixdt/Saturation Dynamic1' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection/I_backCalc_fixdt' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection/I_backCalc_fixdt1' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection/I_backCalc_fixdt/Integrator' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection/I_backCalc_fixdt/Saturation Dynamic1' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection/I_backCalc_fixdt1/Integrator' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection/I_backCalc_fixdt1/Saturation Dynamic1' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F06_Control_Type_Management/COM_Method' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F06_Control_Type_Management/FOC_Method' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F06_Control_Type_Management/SIN_Method' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F06_Control_Type_Management/SIN_Method/Final_Phase_Advance_Calculation' - * '' : 'BLDCmotorControl_FOC_R2017b_fixdt/BLDC_controller/F06_Control_Type_Management/SIN_Method/Final_Phase_Advance_Calculation/Modulo_fixdt' + * '' : 'BLDCmotor_FOC_R2017b_fixdt' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F04_Field_Weakening' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F06_Control_Type_Management' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/Task_Scheduler' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_01_Edge_Detector' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_02_Position_Calculation' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_03_Direction_Detection' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_04_Speed_Estimation' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_05_Electrical_Angle_Estimation' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_06_Electrical_Angle_Measurement' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_04_Speed_Estimation/Counter' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_04_Speed_Estimation/Raw_Motor_Speed_Estimation' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_04_Speed_Estimation/Counter/rst_Delay' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F01_Estimations/F01_06_Electrical_Angle_Measurement/Modulo_fixdt' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/either_edge' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Default' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Dequalification' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Qualification' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/either_edge' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Dequalification/Counter' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Dequalification/Counter/rst_Delay' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Qualification/Counter' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F02_Diagnostics/Debounce_Filter/Qualification/Counter/rst_Delay' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_01_Mode_Transition_Calculation' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_02_Control_Mode_Manager' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Default_Control_Type' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Default_Mode' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/FOC_Control_Type' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Open_Mode' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Open_Mode/Rate_Limiter' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Open_Mode/rising_edge_init' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Open_Mode/Rate_Limiter/Delay_Init1' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F03_Control_Mode_Manager/F03_03_Input_Target_Synthesis/Open_Mode/Rate_Limiter/Saturation Dynamic' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F04_Field_Weakening/Saturation Dynamic' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F04_Field_Weakening/Saturation Dynamic1' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Clarke_Transform' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Current_Filtering' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Inv_Clarke_Transform' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Inv_Park_Transform' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Park_Transform' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Sine_Cosine_Approximation' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Clarke_Transform/Clarke_PhasesAB' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Clarke_Transform/Clarke_PhasesAC' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Clarke_Transform/Clarke_PhasesBC' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Current_Filtering/Low_Pass_Filter' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Open_Mode' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Speed_Mode' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Torque_Mode' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Vd_Calculation' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Voltage_Mode' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Speed_Mode/PI_clamp_fixdt' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Speed_Mode/PI_clamp_fixdt/Clamping_circuit' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Speed_Mode/PI_clamp_fixdt/Integrator' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Speed_Mode/PI_clamp_fixdt/Saturation_hit' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Torque_Mode/PI_clamp_fixdt' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Torque_Mode/Saturation Dynamic1' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Torque_Mode/PI_clamp_fixdt/Clamping_circuit' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Torque_Mode/PI_clamp_fixdt/Integrator' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Torque_Mode/PI_clamp_fixdt/Saturation_hit' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Vd_Calculation/PI_clamp_fixdt' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Vd_Calculation/Saturation Dynamic' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Vd_Calculation/PI_clamp_fixdt/Clamping_circuit' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Vd_Calculation/PI_clamp_fixdt/Integrator' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Vd_Calculation/PI_clamp_fixdt/Saturation_hit' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/FOC/Voltage_Mode/Saturation Dynamic1' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Speed_Mode_Protection' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Torque_Mode_Protection' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Speed_Mode_Protection/Saturation Dynamic' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Torque_Mode_Protection/I_backCalc_fixdt' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Torque_Mode_Protection/I_backCalc_fixdt/Integrator' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Torque_Mode_Protection/I_backCalc_fixdt/Saturation Dynamic1' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection/I_backCalc_fixdt' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection/I_backCalc_fixdt1' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection/I_backCalc_fixdt/Integrator' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection/I_backCalc_fixdt/Saturation Dynamic1' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection/I_backCalc_fixdt1/Integrator' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F05_Field_Oriented_Control/Motor_Limitations/Voltage_Mode_Protection/I_backCalc_fixdt1/Saturation Dynamic1' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F06_Control_Type_Management/COM_Method' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F06_Control_Type_Management/FOC_Method' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F06_Control_Type_Management/SIN_Method' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F06_Control_Type_Management/SIN_Method/Final_Phase_Advance_Calculation' + * '' : 'BLDCmotor_FOC_R2017b_fixdt/BLDC_controller/F06_Control_Type_Management/SIN_Method/Final_Phase_Advance_Calculation/Modulo_fixdt' */ #endif /* RTW_HEADER_BLDC_controller_h_ */ diff --git a/Inc/config.h b/Inc/config.h index e94d201..9c20a66 100644 --- a/Inc/config.h +++ b/Inc/config.h @@ -152,8 +152,8 @@ #define FIELD_WEAK_ENA 0 // [-] Field Weakening / Phase Advance enable flag: 0 = Disabled (default), 1 = Enabled #define FIELD_WEAK_MAX 5 // [A] Maximum Field Weakening D axis current (only for FOC). Higher current results in higher maximum speed. Up to 10A has been tested using 10" wheels. #define PHASE_ADV_MAX 25 // [deg] Maximum Phase Advance angle (only for SIN). Higher angle results in higher maximum speed. -#define FIELD_WEAK_HI 1500 // [-] Input target High threshold for reaching maximum Field Weakening / Phase Advance. Do NOT set this higher than 1500. -#define FIELD_WEAK_LO 1000 // [-] Input target Low threshold for starting Field Weakening / Phase Advance. Do NOT set this higher than 1000. +#define FIELD_WEAK_HI 1000 // (1000, 1500] Input target High threshold for reaching maximum Field Weakening / Phase Advance. Do NOT set this higher than 1500. +#define FIELD_WEAK_LO 750 // ( 500, 1000] Input target Low threshold for starting Field Weakening / Phase Advance. Do NOT set this higher than 1000. // Extra functionality // #define STANDSTILL_HOLD_ENABLE // [-] Flag to hold the position when standtill is reached. Only available and makes sense for VOLTAGE or TORQUE mode. @@ -184,6 +184,21 @@ +// ############################## CRUISE CONTROL SETTINGS ############################ +/* Cruise Control info: + * enable CRUISE_CONTROL_SUPPORT and (SUPPORT_BUTTONS_LEFT or SUPPORT_BUTTONS_RIGHT depending on which cable is the button installed) + * can be activated/deactivated by pressing button1 (Blue cable) to GND + * when activated, it maintains the current speed by switching to SPD_MODE. Acceleration is still possible via the input request, but when released it resumes to previous set speed. + * when deactivated, it returns to previous control MODE and follows the input request. +*/ +// #define CRUISE_CONTROL_SUPPORT +// #define SUPPORT_BUTTONS_LEFT // Use button1 (Blue Left cable) to activate/deactivate Cruise Control +// #define SUPPORT_BUTTONS_RIGHT // Use button1 (Blue Right cable) to activate/deactivate Cruise Control + +// ######################### END OF CRUISE CONTROL SETTINGS ########################## + + + // ############################### DEBUG SERIAL ############################### /* Connect GND and RX of a 3.3v uart-usb adapter to the left (USART2) or right sensor board cable (USART3) * Be careful not to use the red wire of the cable. 15v will destroye evrything. @@ -378,12 +393,12 @@ #define ADC1_MAX 2500 // max ADC1-value while poti at maximum-position (0 - 4095) #define ADC2_MIN 500 // min ADC2-value while poti at minimum-position (0 - 4095) #define ADC2_MAX 2200 // max ADC2-value while poti at maximum-position (0 - 4095) - #define SPEED_COEFFICIENT 16384 // 1.0f - #define STEER_COEFFICIENT 0 // 0.0f + #define SPEED_COEFFICIENT 16384 // 1.0f + #define STEER_COEFFICIENT 0 // 0.0f // #define INVERT_R_DIRECTION // Invert rotation of right motor // #define INVERT_L_DIRECTION // Invert rotation of left motor - #define SIDEBOARD_SERIAL_USART3 - #define FEEDBACK_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used! + #define SIDEBOARD_SERIAL_USART3 // Tx -> Rx of right sensor board: for LED battery indication. Comment-out if sideboard is not used! + #define FEEDBACK_SERIAL_USART3 // Rx <- Tx of right sensor board: to use photosensors as buttons. Comment-out if sideboard is not used! // #define DEBUG_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used! // Extra functionality diff --git a/Inc/rtwtypes.h b/Inc/rtwtypes.h index 21d3fc2..49ec197 100644 --- a/Inc/rtwtypes.h +++ b/Inc/rtwtypes.h @@ -3,9 +3,9 @@ * * Code generated for Simulink model 'BLDC_controller'. * - * Model version : 1.1260 + * Model version : 1.1284 * Simulink Coder version : 8.13 (R2017b) 24-Jul-2017 - * C/C++ source code generated on : Tue Mar 24 11:01:08 2020 + * C/C++ source code generated on : Sun Oct 11 21:38:56 2020 * * Target selection: ert.tlc * Embedded hardware selection: ARM Compatible->ARM Cortex diff --git a/README.md b/README.md index 4254adc..408606a 100644 --- a/README.md +++ b/README.md @@ -71,9 +71,7 @@ In all FOC control modes, the controller features maximum motor speed and maximu - All the calibratable motor parameters can be found in the 'BLDC_controller_data.c'. I provided you with an already calibrated controller, but if you feel like fine tuning it feel free to do so - The parameters are represented in Fixed-point data type for a more efficient code execution - For calibrating the fixed-point parameters use the [Fixed-Point Viewer](https://github.com/EmanuelFeru/FixedPointViewer) tool - - The parameters data Fixed-point types are given in the following table: - -![Parameters table](/docs/pictures/paramTable.png) + - The controller parameters are given in [this table](https://github.com/EmanuelFeru/bldc-motor-control-FOC/blob/master/02_Figures/paramTable.png) ### Diagnostics diff --git a/Src/BLDC_controller.c b/Src/BLDC_controller.c index 0df807e..2028911 100644 --- a/Src/BLDC_controller.c +++ b/Src/BLDC_controller.c @@ -3,9 +3,9 @@ * * Code generated for Simulink model 'BLDC_controller'. * - * Model version : 1.1260 + * Model version : 1.1284 * Simulink Coder version : 8.13 (R2017b) 24-Jul-2017 - * C/C++ source code generated on : Tue Mar 24 11:01:08 2020 + * C/C++ source code generated on : Sun Oct 11 21:38:56 2020 * * Target selection: ert.tlc * Embedded hardware selection: ARM Compatible->ARM Cortex @@ -101,9 +101,20 @@ int32_T div_nde_s32_floor(int32_T numerator, int32_T denominator); extern void Counter_Init(DW_Counter *localDW, int16_T rtp_z_cntInit); extern int16_T Counter(int16_T rtu_inc, int16_T rtu_max, boolean_T rtu_rst, DW_Counter *localDW); +extern void PI_clamp_fixdt_Init(DW_PI_clamp_fixdt *localDW); extern void PI_clamp_fixdt(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, - int16_T rtu_satMax, int16_T rtu_satMin, int32_T rtu_ext_limProt, int16_T - *rty_out, DW_PI_clamp_fixdt *localDW); + int32_T rtu_init, int16_T rtu_satMax, int16_T rtu_satMin, int32_T + rtu_ext_limProt, int16_T *rty_out, DW_PI_clamp_fixdt *localDW); +extern void PI_clamp_fixdt_g_Init(DW_PI_clamp_fixdt_i *localDW); +extern void PI_clamp_fixdt_g_Reset(DW_PI_clamp_fixdt_i *localDW); +extern int16_T PI_clamp_fixdt_o(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, + int16_T rtu_init, int16_T rtu_satMax, int16_T rtu_satMin, int32_T + rtu_ext_limProt, DW_PI_clamp_fixdt_i *localDW); +extern void PI_clamp_fixdt_k_Init(DW_PI_clamp_fixdt_e *localDW); +extern void PI_clamp_fixdt_b_Reset(DW_PI_clamp_fixdt_e *localDW); +extern int16_T PI_clamp_fixdt_a(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, + int16_T rtu_init, int16_T rtu_satMax, int16_T rtu_satMin, int32_T + rtu_ext_limProt, DW_PI_clamp_fixdt_e *localDW); extern void Low_Pass_Filter_Reset(DW_Low_Pass_Filter *localDW); extern void Low_Pass_Filter(const int16_T rtu_u[2], uint16_T rtu_coef, int16_T rty_y[2], DW_Low_Pass_Filter *localDW); @@ -182,7 +193,7 @@ int32_T div_nde_s32_floor(int32_T numerator, int32_T denominator) /* System initialize for atomic system: '/Counter' */ void Counter_Init(DW_Counter *localDW, int16_T rtp_z_cntInit) { - /* InitializeConditions for UnitDelay: '/UnitDelay' */ + /* InitializeConditions for UnitDelay: '/UnitDelay' */ localDW->UnitDelay_DSTATE = rtp_z_cntInit; } @@ -193,9 +204,9 @@ int16_T Counter(int16_T rtu_inc, int16_T rtu_max, boolean_T rtu_rst, DW_Counter int16_T rtu_rst_0; int16_T rty_cnt_0; - /* Switch: '/Switch1' incorporates: - * Constant: '/Constant23' - * UnitDelay: '/UnitDelay' + /* Switch: '/Switch1' incorporates: + * Constant: '/Constant23' + * UnitDelay: '/UnitDelay' */ if (rtu_rst) { rtu_rst_0 = 0; @@ -203,33 +214,36 @@ int16_T Counter(int16_T rtu_inc, int16_T rtu_max, boolean_T rtu_rst, DW_Counter rtu_rst_0 = localDW->UnitDelay_DSTATE; } - /* End of Switch: '/Switch1' */ + /* End of Switch: '/Switch1' */ - /* Sum: '/Sum1' */ + /* Sum: '/Sum1' */ rty_cnt_0 = (int16_T)(rtu_inc + rtu_rst_0); - /* MinMax: '/MinMax' */ + /* MinMax: '/MinMax' */ if (rty_cnt_0 < rtu_max) { - /* Update for UnitDelay: '/UnitDelay' */ + /* Update for UnitDelay: '/UnitDelay' */ localDW->UnitDelay_DSTATE = rty_cnt_0; } else { - /* Update for UnitDelay: '/UnitDelay' */ + /* Update for UnitDelay: '/UnitDelay' */ localDW->UnitDelay_DSTATE = rtu_max; } - /* End of MinMax: '/MinMax' */ + /* End of MinMax: '/MinMax' */ return rty_cnt_0; } -/* - * Output and update for atomic system: - * '/PI_clamp_fixdt' - * '/PI_clamp_fixdt' - * '/PI_clamp_fixdt' - */ -void PI_clamp_fixdt(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, int16_T - rtu_satMax, int16_T rtu_satMin, int32_T rtu_ext_limProt, - int16_T *rty_out, DW_PI_clamp_fixdt *localDW) +/* System initialize for atomic system: '/PI_clamp_fixdt' */ +void PI_clamp_fixdt_Init(DW_PI_clamp_fixdt *localDW) +{ + /* InitializeConditions for Delay: '/Resettable Delay' */ + localDW->icLoad = 1U; +} + +/* Output and update for atomic system: '/PI_clamp_fixdt' */ +void PI_clamp_fixdt(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, int32_T + rtu_init, int16_T rtu_satMax, int16_T rtu_satMin, int32_T + rtu_ext_limProt, int16_T *rty_out, DW_PI_clamp_fixdt + *localDW) { boolean_T rtb_LowerRelop1_c; boolean_T rtb_UpperRelop_e; @@ -238,8 +252,8 @@ void PI_clamp_fixdt(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, int16_T int32_T tmp; int16_T tmp_0; - /* Sum: '/Sum2' incorporates: - * Product: '/Divide2' + /* Sum: '/Sum2' incorporates: + * Product: '/Divide2' */ q0 = rtu_err * rtu_I; if ((q0 < 0) && (rtu_ext_limProt < MIN_int32_T - q0)) { @@ -250,10 +264,15 @@ void PI_clamp_fixdt(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, int16_T q0 += rtu_ext_limProt; } - /* Switch: '/Switch1' incorporates: - * Constant: '/Constant' - * Sum: '/Sum2' - * UnitDelay: '/UnitDelay1' + /* Delay: '/Resettable Delay' */ + if (localDW->icLoad != 0) { + localDW->ResettableDelay_DSTATE = rtu_init; + } + + /* Switch: '/Switch1' incorporates: + * Constant: '/Constant' + * Sum: '/Sum2' + * UnitDelay: '/UnitDelay1' */ if (localDW->UnitDelay1_DSTATE) { tmp = 0; @@ -261,14 +280,14 @@ void PI_clamp_fixdt(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, int16_T tmp = q0; } - /* End of Switch: '/Switch1' */ + /* End of Switch: '/Switch1' */ - /* Sum: '/Sum1' incorporates: - * UnitDelay: '/UnitDelay' + /* Sum: '/Sum1' incorporates: + * Delay: '/Resettable Delay' */ - rtb_Sum1_n = tmp + localDW->UnitDelay_DSTATE; + rtb_Sum1_n = tmp + localDW->ResettableDelay_DSTATE; - /* Product: '/Divide5' */ + /* Product: '/Divide5' */ tmp = (rtu_err * rtu_P) >> 11; if (tmp > 32767) { tmp = 32767; @@ -278,9 +297,9 @@ void PI_clamp_fixdt(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, int16_T } } - /* Sum: '/Sum1' incorporates: - * DataTypeConversion: '/Data Type Conversion1' - * Product: '/Divide5' + /* Sum: '/Sum1' incorporates: + * DataTypeConversion: '/Data Type Conversion1' + * Product: '/Divide5' */ tmp = (((rtb_Sum1_n >> 16) << 1) + tmp) >> 1; if (tmp > 32767) { @@ -291,33 +310,33 @@ void PI_clamp_fixdt(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, int16_T } } - /* RelationalOperator: '/LowerRelop1' incorporates: - * Sum: '/Sum1' + /* RelationalOperator: '/LowerRelop1' incorporates: + * Sum: '/Sum1' */ rtb_LowerRelop1_c = ((int16_T)tmp > rtu_satMax); - /* RelationalOperator: '/UpperRelop' incorporates: - * Sum: '/Sum1' + /* RelationalOperator: '/UpperRelop' incorporates: + * Sum: '/Sum1' */ rtb_UpperRelop_e = ((int16_T)tmp < rtu_satMin); - /* Switch: '/Switch1' incorporates: - * Sum: '/Sum1' - * Switch: '/Switch3' + /* Switch: '/Switch1' incorporates: + * Sum: '/Sum1' + * Switch: '/Switch3' */ if (rtb_LowerRelop1_c) { *rty_out = rtu_satMax; } else if (rtb_UpperRelop_e) { - /* Switch: '/Switch3' */ + /* Switch: '/Switch3' */ *rty_out = rtu_satMin; } else { *rty_out = (int16_T)tmp; } - /* End of Switch: '/Switch1' */ + /* End of Switch: '/Switch1' */ - /* Signum: '/SignDeltaU2' incorporates: - * Sum: '/Sum2' + /* Signum: '/SignDeltaU2' incorporates: + * Sum: '/Sum2' */ if (q0 < 0) { q0 = -1; @@ -325,10 +344,10 @@ void PI_clamp_fixdt(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, int16_T q0 = (q0 > 0); } - /* End of Signum: '/SignDeltaU2' */ + /* End of Signum: '/SignDeltaU2' */ - /* Signum: '/SignDeltaU3' incorporates: - * Sum: '/Sum1' + /* Signum: '/SignDeltaU3' incorporates: + * Sum: '/Sum1' */ if ((int16_T)tmp < 0) { tmp_0 = -1; @@ -336,37 +355,337 @@ void PI_clamp_fixdt(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, int16_T tmp_0 = (int16_T)((int16_T)tmp > 0); } - /* End of Signum: '/SignDeltaU3' */ + /* End of Signum: '/SignDeltaU3' */ - /* Update for UnitDelay: '/UnitDelay1' incorporates: - * DataTypeConversion: '/DataTypeConv4' - * Logic: '/AND1' - * Logic: '/AND1' - * RelationalOperator: '/Equal1' + /* Update for UnitDelay: '/UnitDelay1' incorporates: + * DataTypeConversion: '/DataTypeConv4' + * Logic: '/AND1' + * Logic: '/AND1' + * RelationalOperator: '/Equal1' */ localDW->UnitDelay1_DSTATE = ((q0 == tmp_0) && (rtb_LowerRelop1_c || rtb_UpperRelop_e)); - /* Update for UnitDelay: '/UnitDelay' */ - localDW->UnitDelay_DSTATE = rtb_Sum1_n; + /* Update for Delay: '/Resettable Delay' */ + localDW->icLoad = 0U; + localDW->ResettableDelay_DSTATE = rtb_Sum1_n; } -/* System reset for atomic system: '/Low_Pass_Filter' */ +/* System initialize for atomic system: '/PI_clamp_fixdt' */ +void PI_clamp_fixdt_g_Init(DW_PI_clamp_fixdt_i *localDW) +{ + /* InitializeConditions for Delay: '/Resettable Delay' */ + localDW->icLoad = 1U; +} + +/* System reset for atomic system: '/PI_clamp_fixdt' */ +void PI_clamp_fixdt_g_Reset(DW_PI_clamp_fixdt_i *localDW) +{ + /* InitializeConditions for UnitDelay: '/UnitDelay1' */ + localDW->UnitDelay1_DSTATE = false; + + /* InitializeConditions for Delay: '/Resettable Delay' */ + localDW->icLoad = 1U; +} + +/* Output and update for atomic system: '/PI_clamp_fixdt' */ +int16_T PI_clamp_fixdt_o(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, + int16_T rtu_init, int16_T rtu_satMax, int16_T rtu_satMin, int32_T + rtu_ext_limProt, DW_PI_clamp_fixdt_i *localDW) +{ + boolean_T rtb_LowerRelop1_l; + boolean_T rtb_UpperRelop_f2; + int32_T rtb_Sum1_o; + int32_T q0; + int32_T tmp; + int16_T tmp_0; + int16_T rty_out_0; + + /* Sum: '/Sum2' incorporates: + * Product: '/Divide2' + */ + q0 = rtu_err * rtu_I; + if ((q0 < 0) && (rtu_ext_limProt < MIN_int32_T - q0)) { + q0 = MIN_int32_T; + } else if ((q0 > 0) && (rtu_ext_limProt > MAX_int32_T - q0)) { + q0 = MAX_int32_T; + } else { + q0 += rtu_ext_limProt; + } + + /* Delay: '/Resettable Delay' */ + if (localDW->icLoad != 0) { + localDW->ResettableDelay_DSTATE = rtu_init << 16; + } + + /* Switch: '/Switch1' incorporates: + * Constant: '/Constant' + * Sum: '/Sum2' + * UnitDelay: '/UnitDelay1' + */ + if (localDW->UnitDelay1_DSTATE) { + tmp = 0; + } else { + tmp = q0; + } + + /* End of Switch: '/Switch1' */ + + /* Sum: '/Sum1' incorporates: + * Delay: '/Resettable Delay' + */ + rtb_Sum1_o = tmp + localDW->ResettableDelay_DSTATE; + + /* Product: '/Divide5' */ + tmp = (rtu_err * rtu_P) >> 11; + if (tmp > 32767) { + tmp = 32767; + } else { + if (tmp < -32768) { + tmp = -32768; + } + } + + /* Sum: '/Sum1' incorporates: + * DataTypeConversion: '/Data Type Conversion1' + * Product: '/Divide5' + */ + tmp = (((rtb_Sum1_o >> 16) << 1) + tmp) >> 1; + if (tmp > 32767) { + tmp = 32767; + } else { + if (tmp < -32768) { + tmp = -32768; + } + } + + /* RelationalOperator: '/LowerRelop1' incorporates: + * Sum: '/Sum1' + */ + rtb_LowerRelop1_l = ((int16_T)tmp > rtu_satMax); + + /* RelationalOperator: '/UpperRelop' incorporates: + * Sum: '/Sum1' + */ + rtb_UpperRelop_f2 = ((int16_T)tmp < rtu_satMin); + + /* Switch: '/Switch1' incorporates: + * Sum: '/Sum1' + * Switch: '/Switch3' + */ + if (rtb_LowerRelop1_l) { + rty_out_0 = rtu_satMax; + } else if (rtb_UpperRelop_f2) { + /* Switch: '/Switch3' */ + rty_out_0 = rtu_satMin; + } else { + rty_out_0 = (int16_T)tmp; + } + + /* End of Switch: '/Switch1' */ + + /* Signum: '/SignDeltaU2' incorporates: + * Sum: '/Sum2' + */ + if (q0 < 0) { + q0 = -1; + } else { + q0 = (q0 > 0); + } + + /* End of Signum: '/SignDeltaU2' */ + + /* Signum: '/SignDeltaU3' incorporates: + * Sum: '/Sum1' + */ + if ((int16_T)tmp < 0) { + tmp_0 = -1; + } else { + tmp_0 = (int16_T)((int16_T)tmp > 0); + } + + /* End of Signum: '/SignDeltaU3' */ + + /* Update for UnitDelay: '/UnitDelay1' incorporates: + * DataTypeConversion: '/DataTypeConv4' + * Logic: '/AND1' + * Logic: '/AND1' + * RelationalOperator: '/Equal1' + */ + localDW->UnitDelay1_DSTATE = ((q0 == tmp_0) && (rtb_LowerRelop1_l || + rtb_UpperRelop_f2)); + + /* Update for Delay: '/Resettable Delay' */ + localDW->icLoad = 0U; + localDW->ResettableDelay_DSTATE = rtb_Sum1_o; + return rty_out_0; +} + +/* System initialize for atomic system: '/PI_clamp_fixdt' */ +void PI_clamp_fixdt_k_Init(DW_PI_clamp_fixdt_e *localDW) +{ + /* InitializeConditions for Delay: '/Resettable Delay' */ + localDW->icLoad = 1U; +} + +/* System reset for atomic system: '/PI_clamp_fixdt' */ +void PI_clamp_fixdt_b_Reset(DW_PI_clamp_fixdt_e *localDW) +{ + /* InitializeConditions for UnitDelay: '/UnitDelay1' */ + localDW->UnitDelay1_DSTATE = false; + + /* InitializeConditions for Delay: '/Resettable Delay' */ + localDW->icLoad = 1U; +} + +/* Output and update for atomic system: '/PI_clamp_fixdt' */ +int16_T PI_clamp_fixdt_a(int16_T rtu_err, uint16_T rtu_P, uint16_T rtu_I, + int16_T rtu_init, int16_T rtu_satMax, int16_T rtu_satMin, int32_T + rtu_ext_limProt, DW_PI_clamp_fixdt_e *localDW) +{ + boolean_T rtb_LowerRelop1_lt; + boolean_T rtb_UpperRelop_i; + int16_T rtb_Sum1_n; + int16_T tmp; + int32_T tmp_0; + int32_T q0; + int16_T rty_out_0; + + /* Sum: '/Sum2' incorporates: + * Product: '/Divide2' + */ + q0 = rtu_err * rtu_I; + if ((q0 < 0) && (rtu_ext_limProt < MIN_int32_T - q0)) { + q0 = MIN_int32_T; + } else if ((q0 > 0) && (rtu_ext_limProt > MAX_int32_T - q0)) { + q0 = MAX_int32_T; + } else { + q0 += rtu_ext_limProt; + } + + /* Delay: '/Resettable Delay' */ + if (localDW->icLoad != 0) { + localDW->ResettableDelay_DSTATE = rtu_init; + } + + /* Switch: '/Switch1' incorporates: + * Constant: '/Constant' + * Sum: '/Sum2' + * UnitDelay: '/UnitDelay1' + */ + if (localDW->UnitDelay1_DSTATE) { + tmp = 0; + } else { + tmp = (int16_T)(((q0 < 0 ? 65535 : 0) + q0) >> 16); + } + + /* End of Switch: '/Switch1' */ + + /* Sum: '/Sum1' incorporates: + * Delay: '/Resettable Delay' + */ + rtb_Sum1_n = (int16_T)(tmp + localDW->ResettableDelay_DSTATE); + + /* Product: '/Divide5' */ + tmp_0 = (rtu_err * rtu_P) >> 11; + if (tmp_0 > 32767) { + tmp_0 = 32767; + } else { + if (tmp_0 < -32768) { + tmp_0 = -32768; + } + } + + /* Sum: '/Sum1' incorporates: + * Product: '/Divide5' + */ + tmp_0 = ((rtb_Sum1_n << 1) + tmp_0) >> 1; + if (tmp_0 > 32767) { + tmp_0 = 32767; + } else { + if (tmp_0 < -32768) { + tmp_0 = -32768; + } + } + + /* RelationalOperator: '/LowerRelop1' incorporates: + * Sum: '/Sum1' + */ + rtb_LowerRelop1_lt = ((int16_T)tmp_0 > rtu_satMax); + + /* RelationalOperator: '/UpperRelop' incorporates: + * Sum: '/Sum1' + */ + rtb_UpperRelop_i = ((int16_T)tmp_0 < rtu_satMin); + + /* Switch: '/Switch1' incorporates: + * Sum: '/Sum1' + * Switch: '/Switch3' + */ + if (rtb_LowerRelop1_lt) { + rty_out_0 = rtu_satMax; + } else if (rtb_UpperRelop_i) { + /* Switch: '/Switch3' */ + rty_out_0 = rtu_satMin; + } else { + rty_out_0 = (int16_T)tmp_0; + } + + /* End of Switch: '/Switch1' */ + + /* Signum: '/SignDeltaU2' incorporates: + * Sum: '/Sum2' + */ + if (q0 < 0) { + q0 = -1; + } else { + q0 = (q0 > 0); + } + + /* End of Signum: '/SignDeltaU2' */ + + /* Signum: '/SignDeltaU3' incorporates: + * Sum: '/Sum1' + */ + if ((int16_T)tmp_0 < 0) { + tmp = -1; + } else { + tmp = (int16_T)((int16_T)tmp_0 > 0); + } + + /* End of Signum: '/SignDeltaU3' */ + + /* Update for UnitDelay: '/UnitDelay1' incorporates: + * DataTypeConversion: '/DataTypeConv4' + * Logic: '/AND1' + * Logic: '/AND1' + * RelationalOperator: '/Equal1' + */ + localDW->UnitDelay1_DSTATE = ((q0 == tmp) && (rtb_LowerRelop1_lt || + rtb_UpperRelop_i)); + + /* Update for Delay: '/Resettable Delay' */ + localDW->icLoad = 0U; + localDW->ResettableDelay_DSTATE = rtb_Sum1_n; + return rty_out_0; +} + +/* System reset for atomic system: '/Low_Pass_Filter' */ void Low_Pass_Filter_Reset(DW_Low_Pass_Filter *localDW) { - /* InitializeConditions for UnitDelay: '/UnitDelay1' */ + /* InitializeConditions for UnitDelay: '/UnitDelay1' */ localDW->UnitDelay1_DSTATE[0] = 0; localDW->UnitDelay1_DSTATE[1] = 0; } -/* Output and update for atomic system: '/Low_Pass_Filter' */ +/* Output and update for atomic system: '/Low_Pass_Filter' */ void Low_Pass_Filter(const int16_T rtu_u[2], uint16_T rtu_coef, int16_T rty_y[2], DW_Low_Pass_Filter *localDW) { int32_T rtb_Sum3_g; - /* Sum: '/Sum2' incorporates: - * UnitDelay: '/UnitDelay1' + /* Sum: '/Sum2' incorporates: + * UnitDelay: '/UnitDelay1' */ rtb_Sum3_g = rtu_u[0] - (localDW->UnitDelay1_DSTATE[0] >> 16); if (rtb_Sum3_g > 32767) { @@ -377,21 +696,21 @@ void Low_Pass_Filter(const int16_T rtu_u[2], uint16_T rtu_coef, int16_T rty_y[2] } } - /* Sum: '/Sum3' incorporates: - * Product: '/Divide3' - * Sum: '/Sum2' - * UnitDelay: '/UnitDelay1' + /* Sum: '/Sum3' incorporates: + * Product: '/Divide3' + * Sum: '/Sum2' + * UnitDelay: '/UnitDelay1' */ rtb_Sum3_g = rtu_coef * rtb_Sum3_g + localDW->UnitDelay1_DSTATE[0]; - /* DataTypeConversion: '/Data Type Conversion' */ + /* DataTypeConversion: '/Data Type Conversion' */ rty_y[0] = (int16_T)(rtb_Sum3_g >> 16); - /* Update for UnitDelay: '/UnitDelay1' */ + /* Update for UnitDelay: '/UnitDelay1' */ localDW->UnitDelay1_DSTATE[0] = rtb_Sum3_g; - /* Sum: '/Sum2' incorporates: - * UnitDelay: '/UnitDelay1' + /* Sum: '/Sum2' incorporates: + * UnitDelay: '/UnitDelay1' */ rtb_Sum3_g = rtu_u[1] - (localDW->UnitDelay1_DSTATE[1] >> 16); if (rtb_Sum3_g > 32767) { @@ -402,112 +721,112 @@ void Low_Pass_Filter(const int16_T rtu_u[2], uint16_T rtu_coef, int16_T rty_y[2] } } - /* Sum: '/Sum3' incorporates: - * Product: '/Divide3' - * Sum: '/Sum2' - * UnitDelay: '/UnitDelay1' + /* Sum: '/Sum3' incorporates: + * Product: '/Divide3' + * Sum: '/Sum2' + * UnitDelay: '/UnitDelay1' */ rtb_Sum3_g = rtu_coef * rtb_Sum3_g + localDW->UnitDelay1_DSTATE[1]; - /* DataTypeConversion: '/Data Type Conversion' */ + /* DataTypeConversion: '/Data Type Conversion' */ rty_y[1] = (int16_T)(rtb_Sum3_g >> 16); - /* Update for UnitDelay: '/UnitDelay1' */ + /* Update for UnitDelay: '/UnitDelay1' */ localDW->UnitDelay1_DSTATE[1] = rtb_Sum3_g; } /* * System initialize for atomic system: - * '/I_backCalc_fixdt' - * '/I_backCalc_fixdt1' - * '/I_backCalc_fixdt' + * '/I_backCalc_fixdt' + * '/I_backCalc_fixdt1' + * '/I_backCalc_fixdt' */ void I_backCalc_fixdt_Init(DW_I_backCalc_fixdt *localDW, int32_T rtp_yInit) { - /* InitializeConditions for UnitDelay: '/UnitDelay' */ + /* InitializeConditions for UnitDelay: '/UnitDelay' */ localDW->UnitDelay_DSTATE_h = rtp_yInit; } /* * Output and update for atomic system: - * '/I_backCalc_fixdt' - * '/I_backCalc_fixdt1' - * '/I_backCalc_fixdt' + * '/I_backCalc_fixdt' + * '/I_backCalc_fixdt1' + * '/I_backCalc_fixdt' */ void I_backCalc_fixdt(int16_T rtu_err, uint16_T rtu_I, uint16_T rtu_Kb, int16_T rtu_satMax, int16_T rtu_satMin, int16_T *rty_out, DW_I_backCalc_fixdt *localDW) { - int32_T rtb_Sum1_e0; + int32_T rtb_Sum1_m; int16_T rtb_DataTypeConversion1_no; - /* Sum: '/Sum2' incorporates: - * Product: '/Divide2' - * UnitDelay: '/UnitDelay' + /* Sum: '/Sum2' incorporates: + * Product: '/Divide2' + * UnitDelay: '/UnitDelay' */ - rtb_Sum1_e0 = (rtu_err * rtu_I) >> 4; - if ((rtb_Sum1_e0 < 0) && (localDW->UnitDelay_DSTATE < MIN_int32_T - - rtb_Sum1_e0)) { - rtb_Sum1_e0 = MIN_int32_T; - } else if ((rtb_Sum1_e0 > 0) && (localDW->UnitDelay_DSTATE > MAX_int32_T - - rtb_Sum1_e0)) { - rtb_Sum1_e0 = MAX_int32_T; + rtb_Sum1_m = (rtu_err * rtu_I) >> 4; + if ((rtb_Sum1_m < 0) && (localDW->UnitDelay_DSTATE < MIN_int32_T - rtb_Sum1_m)) + { + rtb_Sum1_m = MIN_int32_T; + } else if ((rtb_Sum1_m > 0) && (localDW->UnitDelay_DSTATE > MAX_int32_T + - rtb_Sum1_m)) { + rtb_Sum1_m = MAX_int32_T; } else { - rtb_Sum1_e0 += localDW->UnitDelay_DSTATE; + rtb_Sum1_m += localDW->UnitDelay_DSTATE; } - /* End of Sum: '/Sum2' */ + /* End of Sum: '/Sum2' */ - /* Sum: '/Sum1' incorporates: - * UnitDelay: '/UnitDelay' + /* Sum: '/Sum1' incorporates: + * UnitDelay: '/UnitDelay' */ - rtb_Sum1_e0 += localDW->UnitDelay_DSTATE_h; + rtb_Sum1_m += localDW->UnitDelay_DSTATE_h; - /* DataTypeConversion: '/Data Type Conversion1' */ - rtb_DataTypeConversion1_no = (int16_T)(rtb_Sum1_e0 >> 12); + /* DataTypeConversion: '/Data Type Conversion1' */ + rtb_DataTypeConversion1_no = (int16_T)(rtb_Sum1_m >> 12); - /* Switch: '/Switch2' incorporates: - * RelationalOperator: '/LowerRelop1' - * RelationalOperator: '/UpperRelop' - * Switch: '/Switch' + /* Switch: '/Switch2' incorporates: + * RelationalOperator: '/LowerRelop1' + * RelationalOperator: '/UpperRelop' + * Switch: '/Switch' */ if (rtb_DataTypeConversion1_no > rtu_satMax) { *rty_out = rtu_satMax; } else if (rtb_DataTypeConversion1_no < rtu_satMin) { - /* Switch: '/Switch' */ + /* Switch: '/Switch' */ *rty_out = rtu_satMin; } else { *rty_out = rtb_DataTypeConversion1_no; } - /* End of Switch: '/Switch2' */ + /* End of Switch: '/Switch2' */ - /* Update for UnitDelay: '/UnitDelay' incorporates: - * Product: '/Divide1' - * Sum: '/Sum3' + /* Update for UnitDelay: '/UnitDelay' incorporates: + * Product: '/Divide1' + * Sum: '/Sum3' */ localDW->UnitDelay_DSTATE = (int16_T)(*rty_out - rtb_DataTypeConversion1_no) * rtu_Kb; - /* Update for UnitDelay: '/UnitDelay' */ - localDW->UnitDelay_DSTATE_h = rtb_Sum1_e0; + /* Update for UnitDelay: '/UnitDelay' */ + localDW->UnitDelay_DSTATE_h = rtb_Sum1_m; } /* * System initialize for atomic system: - * '/Counter' - * '/Counter' + * '/Counter' + * '/Counter' */ void Counter_b_Init(DW_Counter_l *localDW, uint16_T rtp_z_cntInit) { - /* InitializeConditions for UnitDelay: '/UnitDelay' */ + /* InitializeConditions for UnitDelay: '/UnitDelay' */ localDW->UnitDelay_DSTATE = rtp_z_cntInit; } /* * Output and update for atomic system: - * '/Counter' - * '/Counter' + * '/Counter' + * '/Counter' */ uint16_T Counter_i(uint16_T rtu_inc, uint16_T rtu_max, boolean_T rtu_rst, DW_Counter_l *localDW) @@ -515,9 +834,9 @@ uint16_T Counter_i(uint16_T rtu_inc, uint16_T rtu_max, boolean_T rtu_rst, uint16_T rtu_rst_0; uint16_T rty_cnt_0; - /* Switch: '/Switch1' incorporates: - * Constant: '/Constant23' - * UnitDelay: '/UnitDelay' + /* Switch: '/Switch1' incorporates: + * Constant: '/Constant23' + * UnitDelay: '/UnitDelay' */ if (rtu_rst) { rtu_rst_0 = 0U; @@ -525,39 +844,39 @@ uint16_T Counter_i(uint16_T rtu_inc, uint16_T rtu_max, boolean_T rtu_rst, rtu_rst_0 = localDW->UnitDelay_DSTATE; } - /* End of Switch: '/Switch1' */ + /* End of Switch: '/Switch1' */ - /* Sum: '/Sum1' */ + /* Sum: '/Sum1' */ rty_cnt_0 = (uint16_T)((uint32_T)rtu_inc + rtu_rst_0); - /* MinMax: '/MinMax' */ + /* MinMax: '/MinMax' */ if (rty_cnt_0 < rtu_max) { - /* Update for UnitDelay: '/UnitDelay' */ + /* Update for UnitDelay: '/UnitDelay' */ localDW->UnitDelay_DSTATE = rty_cnt_0; } else { - /* Update for UnitDelay: '/UnitDelay' */ + /* Update for UnitDelay: '/UnitDelay' */ localDW->UnitDelay_DSTATE = rtu_max; } - /* End of MinMax: '/MinMax' */ + /* End of MinMax: '/MinMax' */ return rty_cnt_0; } /* * Output and update for atomic system: - * '/either_edge' + * '/either_edge' * '/either_edge' */ boolean_T either_edge(boolean_T rtu_u, DW_either_edge *localDW) { boolean_T rty_y_0; - /* RelationalOperator: '/Relational Operator' incorporates: - * UnitDelay: '/UnitDelay' + /* RelationalOperator: '/Relational Operator' incorporates: + * UnitDelay: '/UnitDelay' */ rty_y_0 = (rtu_u != localDW->UnitDelay_DSTATE); - /* Update for UnitDelay: '/UnitDelay' */ + /* Update for UnitDelay: '/UnitDelay' */ localDW->UnitDelay_DSTATE = rtu_u; return rty_y_0; } @@ -565,23 +884,23 @@ boolean_T either_edge(boolean_T rtu_u, DW_either_edge *localDW) /* System initialize for atomic system: '/Debounce_Filter' */ void Debounce_Filter_Init(DW_Debounce_Filter *localDW) { - /* SystemInitialize for IfAction SubSystem: '/Qualification' */ + /* SystemInitialize for IfAction SubSystem: '/Qualification' */ - /* SystemInitialize for Atomic SubSystem: '/Counter' */ + /* SystemInitialize for Atomic SubSystem: '/Counter' */ Counter_b_Init(&localDW->Counter_i0, 0U); - /* End of SystemInitialize for SubSystem: '/Counter' */ + /* End of SystemInitialize for SubSystem: '/Counter' */ - /* End of SystemInitialize for SubSystem: '/Qualification' */ + /* End of SystemInitialize for SubSystem: '/Qualification' */ - /* SystemInitialize for IfAction SubSystem: '/Dequalification' */ + /* SystemInitialize for IfAction SubSystem: '/Dequalification' */ - /* SystemInitialize for Atomic SubSystem: '/Counter' */ + /* SystemInitialize for Atomic SubSystem: '/Counter' */ Counter_b_Init(&localDW->Counter_h, 0U); - /* End of SystemInitialize for SubSystem: '/Counter' */ + /* End of SystemInitialize for SubSystem: '/Counter' */ - /* End of SystemInitialize for SubSystem: '/Dequalification' */ + /* End of SystemInitialize for SubSystem: '/Dequalification' */ } /* Output and update for atomic system: '/Debounce_Filter' */ @@ -589,74 +908,74 @@ void Debounce_Filter(boolean_T rtu_u, uint16_T rtu_tAcv, uint16_T rtu_tDeacv, boolean_T *rty_y, DW_Debounce_Filter *localDW) { boolean_T rtb_UnitDelay_o; - uint16_T rtb_Sum1_g3; + uint16_T rtb_Sum1_l; boolean_T rtb_RelationalOperator_f; - /* UnitDelay: '/UnitDelay' */ + /* UnitDelay: '/UnitDelay' */ rtb_UnitDelay_o = localDW->UnitDelay_DSTATE; - /* Outputs for Atomic SubSystem: '/either_edge' */ + /* Outputs for Atomic SubSystem: '/either_edge' */ rtb_RelationalOperator_f = either_edge(rtu_u, &localDW->either_edge_k); - /* End of Outputs for SubSystem: '/either_edge' */ + /* End of Outputs for SubSystem: '/either_edge' */ - /* If: '/If2' incorporates: - * Constant: '/Constant6' - * Constant: '/Constant6' - * Inport: '/yPrev' - * Logic: '/Logical Operator1' - * Logic: '/Logical Operator2' - * Logic: '/Logical Operator3' - * Logic: '/Logical Operator4' + /* If: '/If2' incorporates: + * Constant: '/Constant6' + * Constant: '/Constant6' + * Inport: '/yPrev' + * Logic: '/Logical Operator1' + * Logic: '/Logical Operator2' + * Logic: '/Logical Operator3' + * Logic: '/Logical Operator4' */ if (rtu_u && (!rtb_UnitDelay_o)) { - /* Outputs for IfAction SubSystem: '/Qualification' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Qualification' incorporates: + * ActionPort: '/Action Port' */ - /* Outputs for Atomic SubSystem: '/Counter' */ - rtb_Sum1_g3 = (uint16_T) Counter_i(1U, rtu_tAcv, rtb_RelationalOperator_f, + /* Outputs for Atomic SubSystem: '/Counter' */ + rtb_Sum1_l = (uint16_T) Counter_i(1U, rtu_tAcv, rtb_RelationalOperator_f, &localDW->Counter_i0); - /* End of Outputs for SubSystem: '/Counter' */ + /* End of Outputs for SubSystem: '/Counter' */ - /* Switch: '/Switch2' incorporates: - * Constant: '/Constant6' - * RelationalOperator: '/Relational Operator2' + /* Switch: '/Switch2' incorporates: + * Constant: '/Constant6' + * RelationalOperator: '/Relational Operator2' */ - *rty_y = (rtb_Sum1_g3 > rtu_tAcv); + *rty_y = (rtb_Sum1_l > rtu_tAcv); - /* End of Outputs for SubSystem: '/Qualification' */ + /* End of Outputs for SubSystem: '/Qualification' */ } else if ((!rtu_u) && rtb_UnitDelay_o) { - /* Outputs for IfAction SubSystem: '/Dequalification' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Dequalification' incorporates: + * ActionPort: '/Action Port' */ - /* Outputs for Atomic SubSystem: '/Counter' */ - rtb_Sum1_g3 = (uint16_T) Counter_i(1U, rtu_tDeacv, rtb_RelationalOperator_f, + /* Outputs for Atomic SubSystem: '/Counter' */ + rtb_Sum1_l = (uint16_T) Counter_i(1U, rtu_tDeacv, rtb_RelationalOperator_f, &localDW->Counter_h); - /* End of Outputs for SubSystem: '/Counter' */ + /* End of Outputs for SubSystem: '/Counter' */ - /* Switch: '/Switch2' incorporates: - * Constant: '/Constant6' - * RelationalOperator: '/Relational Operator2' + /* Switch: '/Switch2' incorporates: + * Constant: '/Constant6' + * RelationalOperator: '/Relational Operator2' */ - *rty_y = !(rtb_Sum1_g3 > rtu_tDeacv); + *rty_y = !(rtb_Sum1_l > rtu_tDeacv); - /* End of Outputs for SubSystem: '/Dequalification' */ + /* End of Outputs for SubSystem: '/Dequalification' */ } else { - /* Outputs for IfAction SubSystem: '/Default' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Default' incorporates: + * ActionPort: '/Action Port' */ *rty_y = rtb_UnitDelay_o; - /* End of Outputs for SubSystem: '/Default' */ + /* End of Outputs for SubSystem: '/Default' */ } - /* End of If: '/If2' */ + /* End of If: '/If2' */ - /* Update for UnitDelay: '/UnitDelay' */ + /* Update for UnitDelay: '/UnitDelay' */ localDW->UnitDelay_DSTATE = *rty_y; } @@ -669,19 +988,20 @@ void BLDC_controller_step(RT_MODEL *const rtM) ExtY *rtY = (ExtY *) rtM->outputs; uint8_T rtb_Sum; boolean_T rtb_LogicalOperator; - boolean_T rtb_RelationalOperator9; int8_T rtb_Sum2_h; boolean_T rtb_RelationalOperator4_d; boolean_T rtb_RelationalOperator1_m; uint8_T rtb_Sum_l; + boolean_T rtb_LogicalOperator2_p; + boolean_T rtb_LogicalOperator4; int16_T rtb_Switch2_k; int16_T rtb_Abs5; - int16_T rtb_Switch2_fl; - int16_T rtb_Switch1_l; int16_T rtb_DataTypeConversion2; + int16_T rtb_Switch1_l; + int16_T rtb_Saturation; int16_T rtb_Saturation1; - int16_T rtb_Switch2_l; int16_T rtb_Merge; + int16_T rtb_Switch2_l; int16_T rtb_toNegative; int32_T rtb_DataTypeConversion; int32_T rtb_Switch1; @@ -690,7 +1010,7 @@ void BLDC_controller_step(RT_MODEL *const rtM) int16_T rtb_TmpSignalConversionAtLow_Pa[2]; int16_T tmp[4]; int8_T UnitDelay3; - int16_T rtb_Merge_f_idx_1; + int16_T rtb_Merge_f_idx_2; /* Outputs for Atomic SubSystem: '/BLDC_controller' */ /* Sum: '/Sum' incorporates: @@ -717,7 +1037,7 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* If: '/If2' incorporates: * If: '/If2' - * Inport: '/z_counterRawPrev' + * Inport: '/z_counterRawPrev' * UnitDelay: '/UnitDelay3' */ if (rtb_LogicalOperator) { @@ -761,27 +1081,27 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* End of Outputs for SubSystem: '/F01_03_Direction_Detection' */ /* Outputs for IfAction SubSystem: '/Raw_Motor_Speed_Estimation' incorporates: - * ActionPort: '/Action Port' + * ActionPort: '/Action Port' */ rtDW->z_counterRawPrev = rtDW->UnitDelay3_DSTATE; - /* Sum: '/Sum7' incorporates: - * Inport: '/z_counterRawPrev' + /* Sum: '/Sum7' incorporates: + * Inport: '/z_counterRawPrev' * UnitDelay: '/UnitDelay3' - * UnitDelay: '/UnitDelay4' + * UnitDelay: '/UnitDelay4' */ rtb_Switch2_k = (int16_T)(rtDW->z_counterRawPrev - rtDW->UnitDelay4_DSTATE); - /* Abs: '/Abs2' */ + /* Abs: '/Abs2' */ if (rtb_Switch2_k < 0) { rtb_Switch1_l = (int16_T)-rtb_Switch2_k; } else { rtb_Switch1_l = rtb_Switch2_k; } - /* End of Abs: '/Abs2' */ + /* End of Abs: '/Abs2' */ - /* Relay: '/dz_cntTrnsDet' */ + /* Relay: '/dz_cntTrnsDet' */ if (rtb_Switch1_l >= rtP->dz_cntTrnsDetHi) { rtDW->dz_cntTrnsDet_Mode = true; } else { @@ -792,71 +1112,71 @@ void BLDC_controller_step(RT_MODEL *const rtM) rtDW->dz_cntTrnsDet = rtDW->dz_cntTrnsDet_Mode; - /* End of Relay: '/dz_cntTrnsDet' */ + /* End of Relay: '/dz_cntTrnsDet' */ - /* RelationalOperator: '/Relational Operator4' */ + /* RelationalOperator: '/Relational Operator4' */ rtb_RelationalOperator4_d = (rtDW->Switch2_e != UnitDelay3); - /* Switch: '/Switch3' incorporates: - * Constant: '/Constant4' - * Logic: '/Logical Operator1' - * Switch: '/Switch1' - * Switch: '/Switch2' - * UnitDelay: '/UnitDelay1' + /* Switch: '/Switch3' incorporates: + * Constant: '/Constant4' + * Logic: '/Logical Operator1' + * Switch: '/Switch1' + * Switch: '/Switch2' + * UnitDelay: '/UnitDelay1' */ if (rtb_RelationalOperator4_d && rtDW->UnitDelay1_DSTATE_n) { rtb_Switch1_l = 0; } else if (rtb_RelationalOperator4_d) { - /* Switch: '/Switch2' incorporates: + /* Switch: '/Switch2' incorporates: * UnitDelay: '/UnitDelay4' */ rtb_Switch1_l = rtDW->UnitDelay4_DSTATE_e; } else if (rtDW->dz_cntTrnsDet) { - /* Switch: '/Switch1' incorporates: - * Constant: '/cf_speedCoef' - * Product: '/Divide14' - * Switch: '/Switch2' + /* Switch: '/Switch1' incorporates: + * Constant: '/cf_speedCoef' + * Product: '/Divide14' + * Switch: '/Switch2' */ rtb_Switch1_l = (int16_T)((rtP->cf_speedCoef << 4) / rtDW->z_counterRawPrev); } else { - /* Switch: '/Switch1' incorporates: - * Constant: '/cf_speedCoef' - * Gain: '/g_Ha' - * Product: '/Divide13' - * Sum: '/Sum13' - * Switch: '/Switch2' - * UnitDelay: '/UnitDelay2' - * UnitDelay: '/UnitDelay3' - * UnitDelay: '/UnitDelay5' + /* Switch: '/Switch1' incorporates: + * Constant: '/cf_speedCoef' + * Gain: '/g_Ha' + * Product: '/Divide13' + * Sum: '/Sum13' + * Switch: '/Switch2' + * UnitDelay: '/UnitDelay2' + * UnitDelay: '/UnitDelay3' + * UnitDelay: '/UnitDelay5' */ rtb_Switch1_l = (int16_T)(((uint16_T)(rtP->cf_speedCoef << 2) << 4) / (int16_T)(((rtDW->UnitDelay2_DSTATE + rtDW->UnitDelay3_DSTATE_o) + rtDW->UnitDelay5_DSTATE) + rtDW->z_counterRawPrev)); } - /* End of Switch: '/Switch3' */ + /* End of Switch: '/Switch3' */ - /* Product: '/Divide11' */ + /* Product: '/Divide11' */ rtDW->Divide11 = (int16_T)(rtb_Switch1_l * rtDW->Switch2_e); - /* Update for UnitDelay: '/UnitDelay4' */ + /* Update for UnitDelay: '/UnitDelay4' */ rtDW->UnitDelay4_DSTATE = rtDW->z_counterRawPrev; - /* Update for UnitDelay: '/UnitDelay2' incorporates: - * UnitDelay: '/UnitDelay3' + /* Update for UnitDelay: '/UnitDelay2' incorporates: + * UnitDelay: '/UnitDelay3' */ rtDW->UnitDelay2_DSTATE = rtDW->UnitDelay3_DSTATE_o; - /* Update for UnitDelay: '/UnitDelay3' incorporates: - * UnitDelay: '/UnitDelay5' + /* Update for UnitDelay: '/UnitDelay3' incorporates: + * UnitDelay: '/UnitDelay5' */ rtDW->UnitDelay3_DSTATE_o = rtDW->UnitDelay5_DSTATE; - /* Update for UnitDelay: '/UnitDelay5' */ + /* Update for UnitDelay: '/UnitDelay5' */ rtDW->UnitDelay5_DSTATE = rtDW->z_counterRawPrev; - /* Update for UnitDelay: '/UnitDelay1' */ + /* Update for UnitDelay: '/UnitDelay1' */ rtDW->UnitDelay1_DSTATE_n = rtb_RelationalOperator4_d; /* End of Outputs for SubSystem: '/Raw_Motor_Speed_Estimation' */ @@ -905,96 +1225,23 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* Logic: '/Logical Operator2' incorporates: + /* Logic: '/Logical Operator3' incorporates: + * Constant: '/b_angleMeasEna' * Logic: '/Logical Operator1' + * Logic: '/Logical Operator2' * Relay: '/n_commDeacv' */ - rtb_LogicalOperator = (rtDW->n_commDeacv_Mode && (!rtDW->dz_cntTrnsDet)); - - /* Switch: '/Switch2' incorporates: - * Constant: '/Constant16' - * Product: '/Divide1' - * Product: '/Divide3' - * RelationalOperator: '/Relational Operator7' - * Sum: '/Sum3' - * Switch: '/Switch3' - */ - if (rtb_LogicalOperator) { - /* MinMax: '/MinMax' */ - rtb_Switch2_fl = rtb_Switch1_l; - if (!(rtb_Switch2_fl < rtDW->z_counterRawPrev)) { - rtb_Switch2_fl = rtDW->z_counterRawPrev; - } - - /* End of MinMax: '/MinMax' */ - - /* Switch: '/Switch3' incorporates: - * Constant: '/vec_hallToPos' - * Constant: '/Constant16' - * RelationalOperator: '/Relational Operator7' - * Selector: '/Selector' - * Sum: '/Sum1' - */ - if (rtDW->Switch2_e == 1) { - rtb_Sum2_h = rtConstP.vec_hallToPos_Value[rtb_Sum]; - } else { - rtb_Sum2_h = (int8_T)(rtConstP.vec_hallToPos_Value[rtb_Sum] + 1); - } - - rtb_Switch2_fl = (int16_T)(((int16_T)((int16_T)((rtb_Switch2_fl << 14) / - rtDW->z_counterRawPrev) * rtDW->Switch2_e) + (rtb_Sum2_h << 14)) >> 2); - } else { - if (rtDW->Switch2_e == 1) { - /* Switch: '/Switch3' incorporates: - * Constant: '/vec_hallToPos' - * Selector: '/Selector' - */ - rtb_Sum2_h = rtConstP.vec_hallToPos_Value[rtb_Sum]; - } else { - /* Switch: '/Switch3' incorporates: - * Constant: '/vec_hallToPos' - * Selector: '/Selector' - * Sum: '/Sum1' - */ - rtb_Sum2_h = (int8_T)(rtConstP.vec_hallToPos_Value[rtb_Sum] + 1); - } - - rtb_Switch2_fl = (int16_T)(rtb_Sum2_h << 12); - } - - /* End of Switch: '/Switch2' */ - - /* MinMax: '/MinMax1' incorporates: - * Constant: '/Constant1' - */ - if (!(rtb_Switch2_fl > 0)) { - rtb_Switch2_fl = 0; - } - - /* End of MinMax: '/MinMax1' */ - - /* Product: '/Divide2' */ - rtb_Switch2_fl = (int16_T)((15 * rtb_Switch2_fl) >> 4); + rtb_LogicalOperator = (rtP->b_angleMeasEna || (rtDW->n_commDeacv_Mode && + (!rtDW->dz_cntTrnsDet))); /* DataTypeConversion: '/Data Type Conversion2' incorporates: * Inport: '/r_inpTgt' */ - if (rtU->r_inpTgt > 2047) { - rtb_DataTypeConversion2 = MAX_int16_T; - } else if (rtU->r_inpTgt <= -2048) { - rtb_DataTypeConversion2 = MIN_int16_T; - } else { - rtb_DataTypeConversion2 = (int16_T)(rtU->r_inpTgt << 4); - } + rtb_DataTypeConversion2 = (int16_T)(rtU->r_inpTgt << 4); /* UnitDelay: '/UnitDelay2' */ rtb_RelationalOperator4_d = rtDW->UnitDelay2_DSTATE_g; - /* RelationalOperator: '/Relational Operator9' incorporates: - * Constant: '/n_stdStillDet' - */ - rtb_RelationalOperator9 = (rtb_Abs5 < rtP->n_stdStillDet); - /* If: '/If2' incorporates: * Constant: '/b_diagEna' * Constant: '/CTRL_COMM2' @@ -1010,10 +1257,12 @@ void BLDC_controller_step(RT_MODEL *const rtM) */ /* Switch: '/Switch3' incorporates: * Abs: '/Abs4' + * Constant: '/n_stdStillDet' * Constant: '/CTRL_COMM4' * Constant: '/r_errInpTgtThres' * Inport: '/b_motEna' * Logic: '/Logical Operator1' + * RelationalOperator: '/Relational Operator9' * RelationalOperator: '/Relational Operator7' * S-Function (sfix_bitop): '/Bitwise Operator1' * UnitDelay: '/UnitDelay' @@ -1026,16 +1275,16 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* Abs: '/Abs4' incorporates: * UnitDelay: '/UnitDelay4' */ - rtb_Merge_f_idx_1 = (int16_T)-rtDW->UnitDelay4_DSTATE_eu; + rtb_Merge_f_idx_2 = (int16_T)-rtDW->UnitDelay4_DSTATE_eu; } else { /* Abs: '/Abs4' incorporates: * UnitDelay: '/UnitDelay4' */ - rtb_Merge_f_idx_1 = rtDW->UnitDelay4_DSTATE_eu; + rtb_Merge_f_idx_2 = rtDW->UnitDelay4_DSTATE_eu; } - rtb_RelationalOperator1_m = (rtU->b_motEna && rtb_RelationalOperator9 && - (rtb_Merge_f_idx_1 > rtP->r_errInpTgtThres)); + rtb_RelationalOperator1_m = (rtU->b_motEna && (rtb_Abs5 < + rtP->n_stdStillDet) && (rtb_Merge_f_idx_2 > rtP->r_errInpTgtThres)); } /* End of Switch: '/Switch3' */ @@ -1091,7 +1340,7 @@ void BLDC_controller_step(RT_MODEL *const rtM) rtDW->If4_ActiveSubsystem = UnitDelay3; if ((rtb_Sum2_h != UnitDelay3) && (rtb_Sum2_h == 0)) { - /* Disable for If: '/If2' */ + /* Disable for If: '/If2' */ rtDW->If2_ActiveSubsystem = -1; } @@ -1099,44 +1348,48 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* Outputs for IfAction SubSystem: '/F03_Control_Mode_Manager' incorporates: * ActionPort: '/Action Port' */ - /* Logic: '/Logical Operator4' incorporates: - * Constant: '/constant2' - * Constant: '/constant8' + /* Logic: '/Logical Operator1' incorporates: + * Constant: '/b_cruiseCtrlEna' + * Constant: '/constant1' + * Inport: '/z_ctrlModReq' + * RelationalOperator: '/Relational Operator1' + */ + rtb_RelationalOperator1_m = ((rtU->z_ctrlModReq == 2) || + rtP->b_cruiseCtrlEna); + + /* Logic: '/Logical Operator2' incorporates: + * Constant: '/b_cruiseCtrlEna' + * Constant: '/constant' + * Inport: '/z_ctrlModReq' + * Logic: '/Logical Operator5' + * RelationalOperator: '/Relational Operator4' + */ + rtb_LogicalOperator2_p = ((rtU->z_ctrlModReq == 3) && (!rtP->b_cruiseCtrlEna)); + + /* Logic: '/Logical Operator4' incorporates: + * Constant: '/constant8' * Inport: '/b_motEna' * Inport: '/z_ctrlModReq' - * Logic: '/Logical Operator1' - * Logic: '/Logical Operator7' - * RelationalOperator: '/Relational Operator10' - * RelationalOperator: '/Relational Operator11' - * RelationalOperator: '/Relational Operator2' - * UnitDelay: '/UnitDelay1' + * Logic: '/Logical Operator7' + * RelationalOperator: '/Relational Operator10' */ - rtb_RelationalOperator1_m = ((!rtU->b_motEna) || rtDW->Merge_n || - (rtU->z_ctrlModReq == 0) || ((rtU->z_ctrlModReq != rtDW->z_ctrlMod) && - (rtDW->z_ctrlMod != 0))); + rtb_LogicalOperator4 = (rtDW->Merge_n || (!rtU->b_motEna) || + (rtU->z_ctrlModReq == 0)); /* Chart: '/F03_02_Control_Mode_Manager' incorporates: - * Constant: '/constant' - * Constant: '/constant1' - * Constant: '/constant5' - * Constant: '/constant6' - * Constant: '/constant7' + * Constant: '/constant5' * Inport: '/z_ctrlModReq' - * Logic: '/Logical Operator3' - * Logic: '/Logical Operator6' - * Logic: '/Logical Operator9' - * RelationalOperator: '/Relational Operator1' - * RelationalOperator: '/Relational Operator3' - * RelationalOperator: '/Relational Operator4' - * RelationalOperator: '/Relational Operator5' - * RelationalOperator: '/Relational Operator6' + * Logic: '/Logical Operator3' + * Logic: '/Logical Operator6' + * Logic: '/Logical Operator9' + * RelationalOperator: '/Relational Operator5' */ if (rtDW->is_active_c1_BLDC_controller == 0U) { rtDW->is_active_c1_BLDC_controller = 1U; rtDW->is_c1_BLDC_controller = IN_OPEN; rtDW->z_ctrlMod = OPEN_MODE; } else if (rtDW->is_c1_BLDC_controller == IN_ACTIVE) { - if (rtb_RelationalOperator1_m) { + if (rtb_LogicalOperator4) { rtDW->is_ACTIVE = IN_NO_ACTIVE_CHILD; rtDW->is_c1_BLDC_controller = IN_OPEN; rtDW->z_ctrlMod = OPEN_MODE; @@ -1144,27 +1397,59 @@ void BLDC_controller_step(RT_MODEL *const rtM) switch (rtDW->is_ACTIVE) { case IN_SPEED_MODE: rtDW->z_ctrlMod = SPD_MODE; + if (!rtb_RelationalOperator1_m) { + rtDW->is_ACTIVE = IN_NO_ACTIVE_CHILD; + if (rtb_LogicalOperator2_p) { + rtDW->is_ACTIVE = IN_TORQUE_MODE; + rtDW->z_ctrlMod = TRQ_MODE; + } else { + rtDW->is_ACTIVE = IN_VOLTAGE_MODE; + rtDW->z_ctrlMod = VLT_MODE; + } + } break; case IN_TORQUE_MODE: rtDW->z_ctrlMod = TRQ_MODE; + if (!rtb_LogicalOperator2_p) { + rtDW->is_ACTIVE = IN_NO_ACTIVE_CHILD; + if (rtb_RelationalOperator1_m) { + rtDW->is_ACTIVE = IN_SPEED_MODE; + rtDW->z_ctrlMod = SPD_MODE; + } else { + rtDW->is_ACTIVE = IN_VOLTAGE_MODE; + rtDW->z_ctrlMod = VLT_MODE; + } + } break; default: rtDW->z_ctrlMod = VLT_MODE; + if (rtb_LogicalOperator2_p || rtb_RelationalOperator1_m) { + rtDW->is_ACTIVE = IN_NO_ACTIVE_CHILD; + if (rtb_LogicalOperator2_p) { + rtDW->is_ACTIVE = IN_TORQUE_MODE; + rtDW->z_ctrlMod = TRQ_MODE; + } else if (rtb_RelationalOperator1_m) { + rtDW->is_ACTIVE = IN_SPEED_MODE; + rtDW->z_ctrlMod = SPD_MODE; + } else { + rtDW->is_ACTIVE = IN_VOLTAGE_MODE; + rtDW->z_ctrlMod = VLT_MODE; + } + } break; } } } else { rtDW->z_ctrlMod = OPEN_MODE; - if ((!rtb_RelationalOperator1_m) && ((rtU->z_ctrlModReq == 1) || - (rtU->z_ctrlModReq == 2) || (rtU->z_ctrlModReq == 3)) && - rtb_RelationalOperator9) { + if ((!rtb_LogicalOperator4) && ((rtU->z_ctrlModReq == 1) || + rtb_RelationalOperator1_m || rtb_LogicalOperator2_p)) { rtDW->is_c1_BLDC_controller = IN_ACTIVE; - if (rtU->z_ctrlModReq == 3) { + if (rtb_LogicalOperator2_p) { rtDW->is_ACTIVE = IN_TORQUE_MODE; rtDW->z_ctrlMod = TRQ_MODE; - } else if (rtU->z_ctrlModReq == 2) { + } else if (rtb_RelationalOperator1_m) { rtDW->is_ACTIVE = IN_SPEED_MODE; rtDW->z_ctrlMod = SPD_MODE; } else { @@ -1176,32 +1461,29 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* End of Chart: '/F03_02_Control_Mode_Manager' */ - /* If: '/If1' incorporates: - * Constant: '/z_ctrlTypSel1' - * DataTypeConversion: '/Data Type Conversion2' - * Inport: '/r_inpTgt' - * Saturate: '/Saturation' + /* If: '/If1' incorporates: + * Constant: '/z_ctrlTypSel' + * Inport: '/r_inpTgt' + * Saturate: '/Saturation' */ if (rtP->z_ctrlTypSel == 2) { - /* Outputs for IfAction SubSystem: '/FOC_Control_Type' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/FOC_Control_Type' incorporates: + * ActionPort: '/Action Port' */ - /* SignalConversion: '/TmpSignal ConversionAtSelectorInport1' incorporates: - * Constant: '/Vd_max' - * Constant: '/constant1' - * Constant: '/i_max' - * Constant: '/n_max' + /* SignalConversion: '/TmpSignal ConversionAtSelectorInport1' incorporates: + * Constant: '/Vd_max' + * Constant: '/constant1' + * Constant: '/i_max' + * Constant: '/n_max' */ tmp[0] = 0; tmp[1] = rtP->Vd_max; tmp[2] = rtP->n_max; tmp[3] = rtP->i_max; - /* End of Outputs for SubSystem: '/FOC_Control_Type' */ + /* End of Outputs for SubSystem: '/FOC_Control_Type' */ - /* Saturate: '/Saturation' incorporates: - * DataTypeConversion: '/Data Type Conversion2' - */ + /* Saturate: '/Saturation' */ if (rtb_DataTypeConversion2 > 16000) { rtb_Merge = 16000; } else if (rtb_DataTypeConversion2 < -16000) { @@ -1210,51 +1492,51 @@ void BLDC_controller_step(RT_MODEL *const rtM) rtb_Merge = rtb_DataTypeConversion2; } - /* Outputs for IfAction SubSystem: '/FOC_Control_Type' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/FOC_Control_Type' incorporates: + * ActionPort: '/Action Port' */ - /* Product: '/Divide1' incorporates: + /* Product: '/Divide1' incorporates: * Inport: '/z_ctrlModReq' - * Product: '/Divide4' - * Selector: '/Selector' + * Product: '/Divide4' + * Selector: '/Selector' */ rtb_Merge = (int16_T)(((uint16_T)((tmp[rtU->z_ctrlModReq] << 5) / 125) * rtb_Merge) >> 12); - /* End of Outputs for SubSystem: '/FOC_Control_Type' */ + /* End of Outputs for SubSystem: '/FOC_Control_Type' */ } else if (rtb_DataTypeConversion2 > 16000) { - /* Outputs for IfAction SubSystem: '/Default_Control_Type' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Default_Control_Type' incorporates: + * ActionPort: '/Action Port' */ - /* Saturate: '/Saturation' incorporates: - * Inport: '/r_inpTgt' + /* Saturate: '/Saturation' incorporates: + * Inport: '/r_inpTgt' */ rtb_Merge = 16000; - /* End of Outputs for SubSystem: '/Default_Control_Type' */ + /* End of Outputs for SubSystem: '/Default_Control_Type' */ } else if (rtb_DataTypeConversion2 < -16000) { - /* Outputs for IfAction SubSystem: '/Default_Control_Type' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Default_Control_Type' incorporates: + * ActionPort: '/Action Port' */ - /* Saturate: '/Saturation' incorporates: - * Inport: '/r_inpTgt' + /* Saturate: '/Saturation' incorporates: + * Inport: '/r_inpTgt' */ rtb_Merge = -16000; - /* End of Outputs for SubSystem: '/Default_Control_Type' */ + /* End of Outputs for SubSystem: '/Default_Control_Type' */ } else { - /* Outputs for IfAction SubSystem: '/Default_Control_Type' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Default_Control_Type' incorporates: + * ActionPort: '/Action Port' */ rtb_Merge = rtb_DataTypeConversion2; - /* End of Outputs for SubSystem: '/Default_Control_Type' */ + /* End of Outputs for SubSystem: '/Default_Control_Type' */ } - /* End of If: '/If1' */ + /* End of If: '/If1' */ - /* If: '/If2' incorporates: - * Inport: '/r_inpTgtScaRaw' + /* If: '/If2' incorporates: + * Inport: '/r_inpTgtScaRaw' */ rtb_Sum2_h = rtDW->If2_ActiveSubsystem; UnitDelay3 = (int8_T)!(rtDW->z_ctrlMod == 0); @@ -1262,139 +1544,139 @@ void BLDC_controller_step(RT_MODEL *const rtM) switch (UnitDelay3) { case 0: if (UnitDelay3 != rtb_Sum2_h) { - /* SystemReset for IfAction SubSystem: '/Open_Mode' incorporates: - * ActionPort: '/Action Port' + /* SystemReset for IfAction SubSystem: '/Open_Mode' incorporates: + * ActionPort: '/Action Port' */ - /* SystemReset for Atomic SubSystem: '/rising_edge_init' */ - /* SystemReset for If: '/If2' incorporates: - * UnitDelay: '/UnitDelay' - * UnitDelay: '/UnitDelay' + /* SystemReset for Atomic SubSystem: '/rising_edge_init' */ + /* SystemReset for If: '/If2' incorporates: + * UnitDelay: '/UnitDelay' + * UnitDelay: '/UnitDelay' */ - rtDW->UnitDelay_DSTATE_e = true; + rtDW->UnitDelay_DSTATE_b = true; - /* End of SystemReset for SubSystem: '/rising_edge_init' */ + /* End of SystemReset for SubSystem: '/rising_edge_init' */ - /* SystemReset for Atomic SubSystem: '/Rate_Limiter' */ + /* SystemReset for Atomic SubSystem: '/Rate_Limiter' */ rtDW->UnitDelay_DSTATE = 0; - /* End of SystemReset for SubSystem: '/Rate_Limiter' */ - /* End of SystemReset for SubSystem: '/Open_Mode' */ + /* End of SystemReset for SubSystem: '/Rate_Limiter' */ + /* End of SystemReset for SubSystem: '/Open_Mode' */ } - /* Outputs for IfAction SubSystem: '/Open_Mode' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Open_Mode' incorporates: + * ActionPort: '/Action Port' */ - /* DataTypeConversion: '/Data Type Conversion' incorporates: + /* DataTypeConversion: '/Data Type Conversion' incorporates: * UnitDelay: '/UnitDelay4' */ rtb_Gain3 = rtDW->UnitDelay4_DSTATE_eu << 12; rtb_DataTypeConversion = (rtb_Gain3 & 134217728) != 0 ? rtb_Gain3 | -134217728 : rtb_Gain3 & 134217727; - /* Outputs for Atomic SubSystem: '/rising_edge_init' */ - /* UnitDelay: '/UnitDelay' */ - rtb_RelationalOperator9 = rtDW->UnitDelay_DSTATE_e; + /* Outputs for Atomic SubSystem: '/rising_edge_init' */ + /* UnitDelay: '/UnitDelay' */ + rtb_RelationalOperator1_m = rtDW->UnitDelay_DSTATE_b; - /* Update for UnitDelay: '/UnitDelay' incorporates: - * Constant: '/Constant' + /* Update for UnitDelay: '/UnitDelay' incorporates: + * Constant: '/Constant' */ - rtDW->UnitDelay_DSTATE_e = false; + rtDW->UnitDelay_DSTATE_b = false; - /* End of Outputs for SubSystem: '/rising_edge_init' */ + /* End of Outputs for SubSystem: '/rising_edge_init' */ - /* Outputs for Atomic SubSystem: '/Rate_Limiter' */ - /* Switch: '/Switch1' incorporates: - * UnitDelay: '/UnitDelay' + /* Outputs for Atomic SubSystem: '/Rate_Limiter' */ + /* Switch: '/Switch1' incorporates: + * UnitDelay: '/UnitDelay' */ - if (rtb_RelationalOperator9) { + if (rtb_RelationalOperator1_m) { rtb_Switch1 = rtb_DataTypeConversion; } else { rtb_Switch1 = rtDW->UnitDelay_DSTATE; } - /* End of Switch: '/Switch1' */ + /* End of Switch: '/Switch1' */ - /* Sum: '/Sum1' */ + /* Sum: '/Sum1' */ rtb_Gain3 = -rtb_Switch1; rtb_Sum1 = (rtb_Gain3 & 134217728) != 0 ? rtb_Gain3 | -134217728 : rtb_Gain3 & 134217727; - /* Switch: '/Switch2' incorporates: - * Constant: '/dV_openRate' - * RelationalOperator: '/LowerRelop1' + /* Switch: '/Switch2' incorporates: + * Constant: '/dV_openRate' + * RelationalOperator: '/LowerRelop1' */ if (rtb_Sum1 > rtP->dV_openRate) { rtb_Sum1 = rtP->dV_openRate; } else { - /* Gain: '/Gain3' */ + /* Gain: '/Gain3' */ rtb_Gain3 = -rtP->dV_openRate; rtb_Gain3 = (rtb_Gain3 & 134217728) != 0 ? rtb_Gain3 | -134217728 : rtb_Gain3 & 134217727; - /* Switch: '/Switch' incorporates: - * RelationalOperator: '/UpperRelop' + /* Switch: '/Switch' incorporates: + * RelationalOperator: '/UpperRelop' */ if (rtb_Sum1 < rtb_Gain3) { rtb_Sum1 = rtb_Gain3; } - /* End of Switch: '/Switch' */ + /* End of Switch: '/Switch' */ } - /* End of Switch: '/Switch2' */ + /* End of Switch: '/Switch2' */ - /* Sum: '/Sum2' */ + /* Sum: '/Sum2' */ rtb_Gain3 = rtb_Sum1 + rtb_Switch1; rtb_Switch1 = (rtb_Gain3 & 134217728) != 0 ? rtb_Gain3 | -134217728 : rtb_Gain3 & 134217727; - /* Switch: '/Switch2' */ - if (rtb_RelationalOperator9) { - /* Update for UnitDelay: '/UnitDelay' */ + /* Switch: '/Switch2' */ + if (rtb_RelationalOperator1_m) { + /* Update for UnitDelay: '/UnitDelay' */ rtDW->UnitDelay_DSTATE = rtb_DataTypeConversion; } else { - /* Update for UnitDelay: '/UnitDelay' */ + /* Update for UnitDelay: '/UnitDelay' */ rtDW->UnitDelay_DSTATE = rtb_Switch1; } - /* End of Switch: '/Switch2' */ - /* End of Outputs for SubSystem: '/Rate_Limiter' */ + /* End of Switch: '/Switch2' */ + /* End of Outputs for SubSystem: '/Rate_Limiter' */ - /* DataTypeConversion: '/Data Type Conversion1' */ + /* DataTypeConversion: '/Data Type Conversion1' */ rtDW->Merge1 = (int16_T)(rtb_Switch1 >> 12); - /* End of Outputs for SubSystem: '/Open_Mode' */ + /* End of Outputs for SubSystem: '/Open_Mode' */ break; case 1: - /* Outputs for IfAction SubSystem: '/Default_Mode' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Default_Mode' incorporates: + * ActionPort: '/Action Port' */ rtDW->Merge1 = rtb_Merge; - /* End of Outputs for SubSystem: '/Default_Mode' */ + /* End of Outputs for SubSystem: '/Default_Mode' */ break; } - /* End of If: '/If2' */ + /* End of If: '/If2' */ /* End of Outputs for SubSystem: '/F03_Control_Mode_Manager' */ } /* End of If: '/If4' */ /* UnitDelay: '/UnitDelay5' */ - rtb_RelationalOperator9 = rtDW->UnitDelay5_DSTATE_l; + rtb_RelationalOperator1_m = rtDW->UnitDelay5_DSTATE_l; /* Saturate: '/Saturation' incorporates: * Inport: '/i_phaAB' */ rtb_Gain3 = rtU->i_phaAB << 4; if (rtb_Gain3 >= 27200) { - rtb_Merge = 27200; + rtb_Saturation = 27200; } else if (rtb_Gain3 <= -27200) { - rtb_Merge = -27200; + rtb_Saturation = -27200; } else { - rtb_Merge = (int16_T)(rtU->i_phaAB << 4); + rtb_Saturation = (int16_T)(rtU->i_phaAB << 4); } /* End of Saturate: '/Saturation' */ @@ -1413,10 +1695,111 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* End of Saturate: '/Saturation1' */ + /* If: '/If1' incorporates: + * Constant: '/b_angleMeasEna' + */ + if (!rtP->b_angleMeasEna) { + /* Outputs for IfAction SubSystem: '/F01_05_Electrical_Angle_Estimation' incorporates: + * ActionPort: '/Action Port' + */ + /* Switch: '/Switch2' incorporates: + * Constant: '/Constant16' + * Product: '/Divide1' + * Product: '/Divide3' + * RelationalOperator: '/Relational Operator7' + * Sum: '/Sum3' + * Switch: '/Switch3' + */ + if (rtb_LogicalOperator) { + /* MinMax: '/MinMax' */ + rtb_Merge = rtb_Switch1_l; + if (!(rtb_Merge < rtDW->z_counterRawPrev)) { + rtb_Merge = rtDW->z_counterRawPrev; + } + + /* End of MinMax: '/MinMax' */ + + /* Switch: '/Switch3' incorporates: + * Constant: '/vec_hallToPos' + * Constant: '/Constant16' + * RelationalOperator: '/Relational Operator7' + * Selector: '/Selector' + * Sum: '/Sum1' + */ + if (rtDW->Switch2_e == 1) { + rtb_Sum2_h = rtConstP.vec_hallToPos_Value[rtb_Sum]; + } else { + rtb_Sum2_h = (int8_T)(rtConstP.vec_hallToPos_Value[rtb_Sum] + 1); + } + + rtb_Merge = (int16_T)(((int16_T)((int16_T)((rtb_Merge << 14) / + rtDW->z_counterRawPrev) * rtDW->Switch2_e) + (rtb_Sum2_h << 14)) >> 2); + } else { + if (rtDW->Switch2_e == 1) { + /* Switch: '/Switch3' incorporates: + * Constant: '/vec_hallToPos' + * Selector: '/Selector' + */ + rtb_Sum2_h = rtConstP.vec_hallToPos_Value[rtb_Sum]; + } else { + /* Switch: '/Switch3' incorporates: + * Constant: '/vec_hallToPos' + * Selector: '/Selector' + * Sum: '/Sum1' + */ + rtb_Sum2_h = (int8_T)(rtConstP.vec_hallToPos_Value[rtb_Sum] + 1); + } + + rtb_Merge = (int16_T)(rtb_Sum2_h << 12); + } + + /* End of Switch: '/Switch2' */ + + /* MinMax: '/MinMax1' incorporates: + * Constant: '/Constant1' + */ + if (!(rtb_Merge > 0)) { + rtb_Merge = 0; + } + + /* End of MinMax: '/MinMax1' */ + + /* SignalConversion: '/Signal Conversion2' incorporates: + * Product: '/Divide2' + */ + rtb_Merge = (int16_T)((15 * rtb_Merge) >> 4); + + /* End of Outputs for SubSystem: '/F01_05_Electrical_Angle_Estimation' */ + } else { + /* Outputs for IfAction SubSystem: '/F01_06_Electrical_Angle_Measurement' incorporates: + * ActionPort: '/Action Port' + */ + /* Sum: '/Sum1' incorporates: + * Constant: '/Constant2' + * Constant: '/n_polePairs' + * Inport: '/a_mechAngle' + * Product: '/Divide' + */ + rtb_DataTypeConversion = rtU->a_mechAngle * rtP->n_polePairs - 480; + + /* DataTypeConversion: '/Data Type Conversion20' incorporates: + * Constant: '/a_elecPeriod' + * Product: '/Divide2' + * Product: '/Divide3' + * Sum: '/Sum3' + */ + rtb_Merge = (int16_T)((int16_T)(rtb_DataTypeConversion - ((int16_T)((int16_T) + div_nde_s32_floor(rtb_DataTypeConversion, 5760) * 360) << 4)) << 2); + + /* End of Outputs for SubSystem: '/F01_06_Electrical_Angle_Measurement' */ + } + + /* End of If: '/If1' */ + /* If: '/If3' incorporates: * Constant: '/CTRL_COMM2' * Constant: '/b_fieldWeakEna' - * Constant: '/z_ctrlTypSel1' + * Constant: '/z_ctrlTypSel' * Logic: '/Logical Operator1' * RelationalOperator: '/Relational Operator1' * UnitDelay: '/UnitDelay5' @@ -1426,34 +1809,32 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* Outputs for IfAction SubSystem: '/F04_Field_Weakening' incorporates: * ActionPort: '/Action Port' */ - /* Abs: '/Abs5' incorporates: - * DataTypeConversion: '/Data Type Conversion2' - */ + /* Abs: '/Abs5' */ if (rtb_DataTypeConversion2 < 0) { rtb_DataTypeConversion2 = (int16_T)-rtb_DataTypeConversion2; } /* End of Abs: '/Abs5' */ - /* Switch: '/Switch2' incorporates: + /* Switch: '/Switch2' incorporates: * Constant: '/r_fieldWeakHi' * Constant: '/r_fieldWeakLo' - * RelationalOperator: '/LowerRelop1' - * RelationalOperator: '/UpperRelop' - * Switch: '/Switch' + * RelationalOperator: '/LowerRelop1' + * RelationalOperator: '/UpperRelop' + * Switch: '/Switch' */ if (rtb_DataTypeConversion2 > rtP->r_fieldWeakHi) { rtb_DataTypeConversion2 = rtP->r_fieldWeakHi; } else { if (rtb_DataTypeConversion2 < rtP->r_fieldWeakLo) { - /* Switch: '/Switch' incorporates: + /* Switch: '/Switch' incorporates: * Constant: '/r_fieldWeakLo' */ rtb_DataTypeConversion2 = rtP->r_fieldWeakLo; } } - /* End of Switch: '/Switch2' */ + /* End of Switch: '/Switch2' */ /* Switch: '/Switch2' incorporates: * Constant: '/CTRL_COMM2' @@ -1462,24 +1843,24 @@ void BLDC_controller_step(RT_MODEL *const rtM) * RelationalOperator: '/Relational Operator1' */ if (rtP->z_ctrlTypSel == 2) { - rtb_Merge_f_idx_1 = rtP->id_fieldWeakMax; + rtb_Merge_f_idx_2 = rtP->id_fieldWeakMax; } else { - rtb_Merge_f_idx_1 = rtP->a_phaAdvMax; + rtb_Merge_f_idx_2 = rtP->a_phaAdvMax; } /* End of Switch: '/Switch2' */ - /* Switch: '/Switch2' incorporates: + /* Switch: '/Switch2' incorporates: * Constant: '/n_fieldWeakAuthHi' * Constant: '/n_fieldWeakAuthLo' - * RelationalOperator: '/LowerRelop1' - * RelationalOperator: '/UpperRelop' - * Switch: '/Switch' + * RelationalOperator: '/LowerRelop1' + * RelationalOperator: '/UpperRelop' + * Switch: '/Switch' */ if (rtb_Abs5 > rtP->n_fieldWeakAuthHi) { rtb_Switch2_l = rtP->n_fieldWeakAuthHi; } else if (rtb_Abs5 < rtP->n_fieldWeakAuthLo) { - /* Switch: '/Switch' incorporates: + /* Switch: '/Switch' incorporates: * Constant: '/n_fieldWeakAuthLo' */ rtb_Switch2_l = rtP->n_fieldWeakAuthLo; @@ -1487,7 +1868,7 @@ void BLDC_controller_step(RT_MODEL *const rtM) rtb_Switch2_l = rtb_Abs5; } - /* End of Switch: '/Switch2' */ + /* End of Switch: '/Switch2' */ /* Product: '/Divide3' incorporates: * Constant: '/n_fieldWeakAuthHi' @@ -1507,7 +1888,7 @@ void BLDC_controller_step(RT_MODEL *const rtM) (rtP->r_fieldWeakHi - rtP->r_fieldWeakLo)) * (uint16_T)(((int16_T) (rtb_Switch2_l - rtP->n_fieldWeakAuthLo) << 15) / (int16_T) (rtP->n_fieldWeakAuthHi - rtP->n_fieldWeakAuthLo))) >> 15) * - rtb_Merge_f_idx_1) >> 15); + rtb_Merge_f_idx_2) >> 15); /* End of Outputs for SubSystem: '/F04_Field_Weakening' */ } @@ -1515,7 +1896,7 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* End of If: '/If3' */ /* If: '/If1' incorporates: - * Constant: '/z_ctrlTypSel1' + * Constant: '/z_ctrlTypSel' */ rtb_Sum2_h = rtDW->If1_ActiveSubsystem; UnitDelay3 = -1; @@ -1527,10 +1908,10 @@ void BLDC_controller_step(RT_MODEL *const rtM) if ((rtb_Sum2_h != UnitDelay3) && (rtb_Sum2_h == 0)) { /* Disable for If: '/If2' */ if (rtDW->If2_ActiveSubsystem_a == 0) { - /* Disable for Outport: '/iq' */ + /* Disable for Outport: '/iq' */ rtDW->DataTypeConversion[0] = 0; - /* Disable for Outport: '/id' */ + /* Disable for Outport: '/id' */ rtDW->DataTypeConversion[1] = 0; } @@ -1538,15 +1919,25 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* End of Disable for If: '/If2' */ + /* Disable for If: '/If1' */ + if (rtDW->If1_ActiveSubsystem_e == 0) { + /* Disable for SwitchCase: '/Switch Case' */ + rtDW->SwitchCase_ActiveSubsystem = -1; + } + + rtDW->If1_ActiveSubsystem_e = -1; + + /* End of Disable for If: '/If1' */ + /* Disable for Outport: '/V_phaABC_FOC' */ rtDW->Gain4[0] = 0; rtDW->Gain4[1] = 0; rtDW->Gain4[2] = 0; - /* Disable for Outport: '/r_devSignal1' */ + /* Disable for Outport: '/iq' */ rtDW->DataTypeConversion[0] = 0; - /* Disable for Outport: '/r_devSignal2' */ + /* Disable for Outport: '/id' */ rtDW->DataTypeConversion[1] = 0; } @@ -1578,22 +1969,22 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* Gain: '/toNegative' */ rtb_toNegative = (int16_T)-rtDW->Divide3; - /* If: '/If1' incorporates: - * Constant: '/b_selPhaABCurrMeas' + /* If: '/If1' incorporates: + * Constant: '/z_selPhaCurMeasABC' */ - if (rtP->b_selPhaABCurrMeas) { - /* Outputs for IfAction SubSystem: '/Clarke_PhasesAB' incorporates: - * ActionPort: '/Action Port' + if (rtP->z_selPhaCurMeasABC == 0) { + /* Outputs for IfAction SubSystem: '/Clarke_PhasesAB' incorporates: + * ActionPort: '/Action Port' */ - /* Gain: '/Gain4' */ - rtb_Gain3 = 18919 * rtb_Merge; + /* Gain: '/Gain4' */ + rtb_Gain3 = 18919 * rtb_Saturation; - /* Gain: '/Gain2' */ + /* Gain: '/Gain2' */ rtb_DataTypeConversion = 18919 * rtb_Saturation1; - /* Sum: '/Sum1' incorporates: - * Gain: '/Gain2' - * Gain: '/Gain4' + /* Sum: '/Sum1' incorporates: + * Gain: '/Gain2' + * Gain: '/Gain4' */ rtb_Gain3 = (((rtb_Gain3 < 0 ? 32767 : 0) + rtb_Gain3) >> 15) + (int16_T) (((rtb_DataTypeConversion < 0 ? 16383 : 0) + rtb_DataTypeConversion) >> @@ -1608,14 +1999,14 @@ void BLDC_controller_step(RT_MODEL *const rtM) rtb_DataTypeConversion2 = (int16_T)rtb_Gain3; - /* End of Sum: '/Sum1' */ - /* End of Outputs for SubSystem: '/Clarke_PhasesAB' */ - } else { - /* Outputs for IfAction SubSystem: '/Clarke_PhasesBC' incorporates: - * ActionPort: '/Action Port' + /* End of Sum: '/Sum1' */ + /* End of Outputs for SubSystem: '/Clarke_PhasesAB' */ + } else if (rtP->z_selPhaCurMeasABC == 1) { + /* Outputs for IfAction SubSystem: '/Clarke_PhasesBC' incorporates: + * ActionPort: '/Action Port' */ - /* Sum: '/Sum3' */ - rtb_Gain3 = rtb_Merge - rtb_Saturation1; + /* Sum: '/Sum3' */ + rtb_Gain3 = rtb_Saturation - rtb_Saturation1; if (rtb_Gain3 > 32767) { rtb_Gain3 = 32767; } else { @@ -1624,15 +2015,15 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* Gain: '/Gain2' incorporates: - * Sum: '/Sum3' + /* Gain: '/Gain2' incorporates: + * Sum: '/Sum3' */ rtb_Gain3 *= 18919; rtb_DataTypeConversion2 = (int16_T)(((rtb_Gain3 < 0 ? 32767 : 0) + rtb_Gain3) >> 15); - /* Sum: '/Sum1' */ - rtb_Gain3 = -rtb_Merge - rtb_Saturation1; + /* Sum: '/Sum1' */ + rtb_Gain3 = -rtb_Saturation - rtb_Saturation1; if (rtb_Gain3 > 32767) { rtb_Gain3 = 32767; } else { @@ -1641,19 +2032,48 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - rtb_Merge = (int16_T)rtb_Gain3; + rtb_Saturation = (int16_T)rtb_Gain3; - /* End of Sum: '/Sum1' */ - /* End of Outputs for SubSystem: '/Clarke_PhasesBC' */ + /* End of Sum: '/Sum1' */ + /* End of Outputs for SubSystem: '/Clarke_PhasesBC' */ + } else { + /* Outputs for IfAction SubSystem: '/Clarke_PhasesAC' incorporates: + * ActionPort: '/Action Port' + */ + /* Gain: '/Gain4' */ + rtb_Gain3 = 18919 * rtb_Saturation; + + /* Gain: '/Gain2' */ + rtb_DataTypeConversion = 18919 * rtb_Saturation1; + + /* Sum: '/Sum1' incorporates: + * Gain: '/Gain2' + * Gain: '/Gain4' + */ + rtb_Gain3 = -(((rtb_Gain3 < 0 ? 32767 : 0) + rtb_Gain3) >> 15) - (int16_T) + (((rtb_DataTypeConversion < 0 ? 16383 : 0) + rtb_DataTypeConversion) >> + 14); + if (rtb_Gain3 > 32767) { + rtb_Gain3 = 32767; + } else { + if (rtb_Gain3 < -32768) { + rtb_Gain3 = -32768; + } + } + + rtb_DataTypeConversion2 = (int16_T)rtb_Gain3; + + /* End of Sum: '/Sum1' */ + /* End of Outputs for SubSystem: '/Clarke_PhasesAC' */ } - /* End of If: '/If1' */ + /* End of If: '/If1' */ - /* PreLookup: '/a_elecAngle_XA' */ - rtb_Sum_l = plook_u8s16_evencka(rtb_Switch2_fl, 0, 128U, 180U); + /* PreLookup: '/a_elecAngle_XA' */ + rtb_Sum_l = plook_u8s16_evencka(rtb_Merge, 0, 128U, 180U); /* If: '/If2' incorporates: - * Constant: '/cf_currFilt' + * Constant: '/cf_currFilt' * Inport: '/b_motEna' */ rtb_Sum2_h = rtDW->If2_ActiveSubsystem_a; @@ -1664,37 +2084,37 @@ void BLDC_controller_step(RT_MODEL *const rtM) rtDW->If2_ActiveSubsystem_a = UnitDelay3; if ((rtb_Sum2_h != UnitDelay3) && (rtb_Sum2_h == 0)) { - /* Disable for Outport: '/iq' */ + /* Disable for Outport: '/iq' */ rtDW->DataTypeConversion[0] = 0; - /* Disable for Outport: '/id' */ + /* Disable for Outport: '/id' */ rtDW->DataTypeConversion[1] = 0; } if (UnitDelay3 == 0) { if (0 != rtb_Sum2_h) { /* SystemReset for IfAction SubSystem: '/Current_Filtering' incorporates: - * ActionPort: '/Action Port' + * ActionPort: '/Action Port' */ - /* SystemReset for Atomic SubSystem: '/Low_Pass_Filter' */ + /* SystemReset for Atomic SubSystem: '/Low_Pass_Filter' */ /* SystemReset for If: '/If2' */ Low_Pass_Filter_Reset(&rtDW->Low_Pass_Filter_m); - /* End of SystemReset for SubSystem: '/Low_Pass_Filter' */ + /* End of SystemReset for SubSystem: '/Low_Pass_Filter' */ /* End of SystemReset for SubSystem: '/Current_Filtering' */ } - /* Sum: '/Sum6' incorporates: - * Interpolation_n-D: '/r_cos_M1' - * Interpolation_n-D: '/r_sin_M1' - * Product: '/Divide1' - * Product: '/Divide4' + /* Sum: '/Sum6' incorporates: + * Interpolation_n-D: '/r_cos_M1' + * Interpolation_n-D: '/r_sin_M1' + * Product: '/Divide1' + * Product: '/Divide4' */ rtb_Gain3 = (int16_T)((rtb_DataTypeConversion2 * - rtConstP.r_cos_M1_Table[rtb_Sum_l]) >> 14) - (int16_T)((rtb_Merge * + rtConstP.r_cos_M1_Table[rtb_Sum_l]) >> 14) - (int16_T)((rtb_Saturation * rtConstP.r_sin_M1_Table[rtb_Sum_l]) >> 14); if (rtb_Gain3 > 32767) { rtb_Gain3 = 32767; @@ -1705,23 +2125,23 @@ void BLDC_controller_step(RT_MODEL *const rtM) } /* Outputs for IfAction SubSystem: '/Current_Filtering' incorporates: - * ActionPort: '/Action Port' + * ActionPort: '/Action Port' */ - /* SignalConversion: '/TmpSignal ConversionAtLow_Pass_FilterInport1' incorporates: - * Sum: '/Sum6' + /* SignalConversion: '/TmpSignal ConversionAtLow_Pass_FilterInport1' incorporates: + * Sum: '/Sum6' */ rtb_TmpSignalConversionAtLow_Pa[0] = (int16_T)rtb_Gain3; /* End of Outputs for SubSystem: '/Current_Filtering' */ - /* Sum: '/Sum1' incorporates: - * Interpolation_n-D: '/r_cos_M1' - * Interpolation_n-D: '/r_sin_M1' - * Product: '/Divide2' - * Product: '/Divide3' + /* Sum: '/Sum1' incorporates: + * Interpolation_n-D: '/r_cos_M1' + * Interpolation_n-D: '/r_sin_M1' + * Product: '/Divide2' + * Product: '/Divide3' */ - rtb_Gain3 = (int16_T)((rtb_Merge * rtConstP.r_cos_M1_Table[rtb_Sum_l]) >> - 14) + (int16_T)((rtb_DataTypeConversion2 * + rtb_Gain3 = (int16_T)((rtb_Saturation * rtConstP.r_cos_M1_Table[rtb_Sum_l]) + >> 14) + (int16_T)((rtb_DataTypeConversion2 * rtConstP.r_sin_M1_Table[rtb_Sum_l]) >> 14); if (rtb_Gain3 > 32767) { rtb_Gain3 = 32767; @@ -1732,18 +2152,18 @@ void BLDC_controller_step(RT_MODEL *const rtM) } /* Outputs for IfAction SubSystem: '/Current_Filtering' incorporates: - * ActionPort: '/Action Port' + * ActionPort: '/Action Port' */ - /* SignalConversion: '/TmpSignal ConversionAtLow_Pass_FilterInport1' incorporates: - * Sum: '/Sum1' + /* SignalConversion: '/TmpSignal ConversionAtLow_Pass_FilterInport1' incorporates: + * Sum: '/Sum1' */ rtb_TmpSignalConversionAtLow_Pa[1] = (int16_T)rtb_Gain3; - /* Outputs for Atomic SubSystem: '/Low_Pass_Filter' */ + /* Outputs for Atomic SubSystem: '/Low_Pass_Filter' */ Low_Pass_Filter(rtb_TmpSignalConversionAtLow_Pa, rtP->cf_currFilt, rtDW->DataTypeConversion, &rtDW->Low_Pass_Filter_m); - /* End of Outputs for SubSystem: '/Low_Pass_Filter' */ + /* End of Outputs for SubSystem: '/Low_Pass_Filter' */ /* End of Outputs for SubSystem: '/Current_Filtering' */ } @@ -1751,45 +2171,45 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* End of If: '/If2' */ /* If: '/If3' incorporates: - * Constant: '/Vd_max1' - * Constant: '/i_max' + * Constant: '/Vd_max1' + * Constant: '/i_max' * UnitDelay: '/UnitDelay5' */ if (rtDW->UnitDelay5_DSTATE_l) { /* Outputs for IfAction SubSystem: '/Motor_Limitations' incorporates: - * ActionPort: '/Action Port' + * ActionPort: '/Action Port' */ rtDW->Vd_max1 = rtP->Vd_max; - /* Gain: '/Gain3' incorporates: - * Constant: '/Vd_max1' + /* Gain: '/Gain3' incorporates: + * Constant: '/Vd_max1' */ rtDW->Gain3 = (int16_T)-rtDW->Vd_max1; - /* Interpolation_n-D: '/Vq_max_M1' incorporates: - * Abs: '/Abs5' - * PreLookup: '/Vq_max_XA' + /* Interpolation_n-D: '/Vq_max_M1' incorporates: + * Abs: '/Abs5' + * PreLookup: '/Vq_max_XA' * UnitDelay: '/UnitDelay4' */ if (rtDW->UnitDelay4_DSTATE_h < 0) { - rtb_Merge_f_idx_1 = (int16_T)-rtDW->UnitDelay4_DSTATE_h; + rtb_Merge_f_idx_2 = (int16_T)-rtDW->UnitDelay4_DSTATE_h; } else { - rtb_Merge_f_idx_1 = rtDW->UnitDelay4_DSTATE_h; + rtb_Merge_f_idx_2 = rtDW->UnitDelay4_DSTATE_h; } - rtDW->Vq_max_M1 = rtP->Vq_max_M1[plook_u8s16_evencka(rtb_Merge_f_idx_1, + rtDW->Vq_max_M1 = rtP->Vq_max_M1[plook_u8s16_evencka(rtb_Merge_f_idx_2, rtP->Vq_max_XA[0], (uint16_T)(rtP->Vq_max_XA[1] - rtP->Vq_max_XA[0]), 45U)]; - /* End of Interpolation_n-D: '/Vq_max_M1' */ + /* End of Interpolation_n-D: '/Vq_max_M1' */ - /* Gain: '/Gain5' */ + /* Gain: '/Gain5' */ rtDW->Gain5 = (int16_T)-rtDW->Vq_max_M1; rtDW->i_max = rtP->i_max; - /* Interpolation_n-D: '/iq_maxSca_M1' incorporates: - * Constant: '/i_max' - * Product: '/Divide4' + /* Interpolation_n-D: '/iq_maxSca_M1' incorporates: + * Constant: '/i_max' + * Product: '/Divide4' */ rtb_Gain3 = rtDW->Divide3 << 16; rtb_Gain3 = (rtb_Gain3 == MIN_int32_T) && (rtDW->i_max == -1) ? @@ -1802,113 +2222,113 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* Product: '/Divide1' incorporates: - * Interpolation_n-D: '/iq_maxSca_M1' - * PreLookup: '/iq_maxSca_XA' - * Product: '/Divide4' + /* Product: '/Divide1' incorporates: + * Interpolation_n-D: '/iq_maxSca_M1' + * PreLookup: '/iq_maxSca_XA' + * Product: '/Divide4' */ rtDW->Divide1_a = (int16_T) ((rtConstP.iq_maxSca_M1_Table[plook_u8u16_evencka((uint16_T)rtb_Gain3, 0U, 1311U, 49U)] * rtDW->i_max) >> 16); - /* Gain: '/Gain1' */ + /* Gain: '/Gain1' */ rtDW->Gain1 = (int16_T)-rtDW->Divide1_a; - /* SwitchCase: '/Switch Case' incorporates: - * Constant: '/n_max1' - * Constant: '/Constant1' - * Constant: '/cf_KbLimProt' - * Constant: '/cf_nKiLimProt' - * Constant: '/Constant' - * Constant: '/Constant1' - * Constant: '/cf_KbLimProt' - * Constant: '/cf_iqKiLimProt' - * Constant: '/cf_nKiLimProt' - * Sum: '/Sum1' - * Sum: '/Sum1' - * Sum: '/Sum2' + /* SwitchCase: '/Switch Case' incorporates: + * Constant: '/n_max1' + * Constant: '/Constant1' + * Constant: '/cf_KbLimProt' + * Constant: '/cf_nKiLimProt' + * Constant: '/Constant' + * Constant: '/Constant1' + * Constant: '/cf_KbLimProt' + * Constant: '/cf_iqKiLimProt' + * Constant: '/cf_nKiLimProt' + * Sum: '/Sum1' + * Sum: '/Sum1' + * Sum: '/Sum2' */ switch (rtDW->z_ctrlMod) { case 1: /* Abs: '/Abs5' */ if (rtDW->DataTypeConversion[0] < 0) { - rtb_Merge_f_idx_1 = (int16_T)-rtDW->DataTypeConversion[0]; + rtb_Merge_f_idx_2 = (int16_T)-rtDW->DataTypeConversion[0]; } else { - rtb_Merge_f_idx_1 = rtDW->DataTypeConversion[0]; + rtb_Merge_f_idx_2 = rtDW->DataTypeConversion[0]; } /* End of Abs: '/Abs5' */ - /* Outputs for IfAction SubSystem: '/Voltage_Mode_Protection' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Voltage_Mode_Protection' incorporates: + * ActionPort: '/Action Port' */ - /* Outputs for Atomic SubSystem: '/I_backCalc_fixdt' */ - I_backCalc_fixdt((int16_T)(rtDW->Divide1_a - rtb_Merge_f_idx_1), + /* Outputs for Atomic SubSystem: '/I_backCalc_fixdt' */ + I_backCalc_fixdt((int16_T)(rtDW->Divide1_a - rtb_Merge_f_idx_2), rtP->cf_iqKiLimProt, rtP->cf_KbLimProt, rtb_Switch2_l, 0, &rtDW->Switch2_c, &rtDW->I_backCalc_fixdt_i); - /* End of Outputs for SubSystem: '/I_backCalc_fixdt' */ + /* End of Outputs for SubSystem: '/I_backCalc_fixdt' */ - /* Outputs for Atomic SubSystem: '/I_backCalc_fixdt1' */ + /* Outputs for Atomic SubSystem: '/I_backCalc_fixdt1' */ I_backCalc_fixdt((int16_T)(rtP->n_max - rtb_Abs5), rtP->cf_nKiLimProt, rtP->cf_KbLimProt, rtb_Switch2_l, 0, &rtDW->Switch2_l, &rtDW->I_backCalc_fixdt1); - /* End of Outputs for SubSystem: '/I_backCalc_fixdt1' */ + /* End of Outputs for SubSystem: '/I_backCalc_fixdt1' */ - /* End of Outputs for SubSystem: '/Voltage_Mode_Protection' */ + /* End of Outputs for SubSystem: '/Voltage_Mode_Protection' */ break; case 2: - /* Outputs for IfAction SubSystem: '/Speed_Mode_Protection' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Speed_Mode_Protection' incorporates: + * ActionPort: '/Action Port' */ - /* Switch: '/Switch2' incorporates: - * RelationalOperator: '/LowerRelop1' - * RelationalOperator: '/UpperRelop' - * Switch: '/Switch' + /* Switch: '/Switch2' incorporates: + * RelationalOperator: '/LowerRelop1' + * RelationalOperator: '/UpperRelop' + * Switch: '/Switch' */ if (rtDW->DataTypeConversion[0] > rtDW->Divide1_a) { - rtb_Merge_f_idx_1 = rtDW->Divide1_a; + rtb_Merge_f_idx_2 = rtDW->Divide1_a; } else if (rtDW->DataTypeConversion[0] < rtDW->Gain1) { - /* Switch: '/Switch' */ - rtb_Merge_f_idx_1 = rtDW->Gain1; + /* Switch: '/Switch' */ + rtb_Merge_f_idx_2 = rtDW->Gain1; } else { - rtb_Merge_f_idx_1 = rtDW->DataTypeConversion[0]; + rtb_Merge_f_idx_2 = rtDW->DataTypeConversion[0]; } - /* End of Switch: '/Switch2' */ + /* End of Switch: '/Switch2' */ - /* Product: '/Divide1' incorporates: - * Constant: '/cf_iqKiLimProt' - * Sum: '/Sum3' + /* Product: '/Divide1' incorporates: + * Constant: '/cf_iqKiLimProt' + * Sum: '/Sum3' */ - rtDW->Divide1 = (int16_T)(rtb_Merge_f_idx_1 - rtDW->DataTypeConversion[0]) + rtDW->Divide1 = (int16_T)(rtb_Merge_f_idx_2 - rtDW->DataTypeConversion[0]) * rtP->cf_iqKiLimProt; - /* End of Outputs for SubSystem: '/Speed_Mode_Protection' */ + /* End of Outputs for SubSystem: '/Speed_Mode_Protection' */ break; case 3: - /* Outputs for IfAction SubSystem: '/Torque_Mode_Protection' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Torque_Mode_Protection' incorporates: + * ActionPort: '/Action Port' */ - /* Outputs for Atomic SubSystem: '/I_backCalc_fixdt' */ + /* Outputs for Atomic SubSystem: '/I_backCalc_fixdt' */ I_backCalc_fixdt((int16_T)(rtP->n_max - rtb_Abs5), rtP->cf_nKiLimProt, rtP->cf_KbLimProt, rtDW->Vq_max_M1, 0, &rtDW->Switch2, &rtDW->I_backCalc_fixdt_g); - /* End of Outputs for SubSystem: '/I_backCalc_fixdt' */ + /* End of Outputs for SubSystem: '/I_backCalc_fixdt' */ - /* End of Outputs for SubSystem: '/Torque_Mode_Protection' */ + /* End of Outputs for SubSystem: '/Torque_Mode_Protection' */ break; } - /* End of SwitchCase: '/Switch Case' */ + /* End of SwitchCase: '/Switch Case' */ - /* Gain: '/Gain4' */ + /* Gain: '/Gain4' */ rtDW->Gain4_c = (int16_T)-rtDW->i_max; /* End of Outputs for SubSystem: '/Motor_Limitations' */ @@ -1919,37 +2339,50 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* If: '/If1' incorporates: * UnitDelay: '/UnitDelay6' */ + rtb_Sum2_h = rtDW->If1_ActiveSubsystem_e; + UnitDelay3 = -1; if (rtDW->UnitDelay6_DSTATE) { + UnitDelay3 = 0; + } + + rtDW->If1_ActiveSubsystem_e = UnitDelay3; + if ((rtb_Sum2_h != UnitDelay3) && (rtb_Sum2_h == 0)) { + /* Disable for SwitchCase: '/Switch Case' */ + rtDW->SwitchCase_ActiveSubsystem = -1; + } + + if (UnitDelay3 == 0) { /* Outputs for IfAction SubSystem: '/FOC' incorporates: - * ActionPort: '/Action Port' + * ActionPort: '/Action Port' */ - /* If: '/If1' incorporates: - * Constant: '/cf_idKi1' - * Constant: '/cf_idKp1' - * Constant: '/constant1' - * Sum: '/Sum3' + /* If: '/If1' incorporates: + * Constant: '/cf_idKi1' + * Constant: '/cf_idKp1' + * Constant: '/constant1' + * Constant: '/constant2' + * Sum: '/Sum3' */ if (rtb_LogicalOperator) { - /* Outputs for IfAction SubSystem: '/Vd_Calculation' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Vd_Calculation' incorporates: + * ActionPort: '/Action Port' */ - /* Switch: '/Switch2' incorporates: - * RelationalOperator: '/LowerRelop1' - * RelationalOperator: '/UpperRelop' - * Switch: '/Switch' + /* Switch: '/Switch2' incorporates: + * RelationalOperator: '/LowerRelop1' + * RelationalOperator: '/UpperRelop' + * Switch: '/Switch' */ if (rtb_toNegative > rtDW->i_max) { rtb_toNegative = rtDW->i_max; } else { if (rtb_toNegative < rtDW->Gain4_c) { - /* Switch: '/Switch' */ + /* Switch: '/Switch' */ rtb_toNegative = rtDW->Gain4_c; } } - /* End of Switch: '/Switch2' */ + /* End of Switch: '/Switch2' */ - /* Sum: '/Sum3' */ + /* Sum: '/Sum3' */ rtb_Gain3 = rtb_toNegative - rtDW->DataTypeConversion[1]; if (rtb_Gain3 > 32767) { rtb_Gain3 = 32767; @@ -1959,34 +2392,54 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* Outputs for Atomic SubSystem: '/PI_clamp_fixdt' */ - PI_clamp_fixdt((int16_T)rtb_Gain3, rtP->cf_idKp, rtP->cf_idKi, + /* Outputs for Atomic SubSystem: '/PI_clamp_fixdt' */ + PI_clamp_fixdt((int16_T)rtb_Gain3, rtP->cf_idKp, rtP->cf_idKi, 0, rtDW->Vd_max1, rtDW->Gain3, 0, &rtDW->Switch1, &rtDW->PI_clamp_fixdt_k); - /* End of Outputs for SubSystem: '/PI_clamp_fixdt' */ + /* End of Outputs for SubSystem: '/PI_clamp_fixdt' */ - /* End of Outputs for SubSystem: '/Vd_Calculation' */ + /* End of Outputs for SubSystem: '/Vd_Calculation' */ } - /* End of If: '/If1' */ + /* End of If: '/If1' */ - /* SwitchCase: '/Switch Case' incorporates: - * Constant: '/cf_nKi' - * Constant: '/cf_nKp' - * Constant: '/cf_iqKi' - * Constant: '/cf_iqKp' - * Constant: '/constant2' - * Inport: '/r_inpTgtSca' - * Sum: '/Sum3' - * Sum: '/Sum2' + /* SwitchCase: '/Switch Case' incorporates: + * Constant: '/cf_nKi' + * Constant: '/cf_nKp' + * Constant: '/cf_iqKi' + * Constant: '/cf_iqKp' + * Constant: '/constant2' + * Inport: '/r_inpTgtSca' + * Sum: '/Sum3' + * Sum: '/Sum2' + * UnitDelay: '/UnitDelay4' */ + rtb_Sum2_h = rtDW->SwitchCase_ActiveSubsystem; switch (rtDW->z_ctrlMod) { case 1: - /* Outputs for IfAction SubSystem: '/Voltage_Mode' incorporates: - * ActionPort: '/Action Port' + break; + + case 2: + UnitDelay3 = 1; + break; + + case 3: + UnitDelay3 = 2; + break; + + default: + UnitDelay3 = 3; + break; + } + + rtDW->SwitchCase_ActiveSubsystem = UnitDelay3; + switch (UnitDelay3) { + case 0: + /* Outputs for IfAction SubSystem: '/Voltage_Mode' incorporates: + * ActionPort: '/Action Port' */ - /* MinMax: '/MinMax' */ + /* MinMax: '/MinMax' */ if (!(rtb_Switch2_l < rtDW->Switch2_c)) { rtb_Switch2_l = rtDW->Switch2_c; } @@ -1995,50 +2448,177 @@ void BLDC_controller_step(RT_MODEL *const rtM) rtb_Switch2_l = rtDW->Switch2_l; } - /* End of MinMax: '/MinMax' */ + /* End of MinMax: '/MinMax' */ - /* Signum: '/SignDeltaU2' */ + /* Signum: '/SignDeltaU2' */ if (rtDW->Merge1 < 0) { - rtb_Merge_f_idx_1 = -1; + rtb_Merge_f_idx_2 = -1; } else { - rtb_Merge_f_idx_1 = (int16_T)(rtDW->Merge1 > 0); + rtb_Merge_f_idx_2 = (int16_T)(rtDW->Merge1 > 0); } - /* End of Signum: '/SignDeltaU2' */ + /* End of Signum: '/SignDeltaU2' */ - /* Product: '/Divide1' */ - rtb_Merge = (int16_T)(rtb_Switch2_l * rtb_Merge_f_idx_1); + /* Product: '/Divide1' */ + rtb_Saturation = (int16_T)(rtb_Switch2_l * rtb_Merge_f_idx_2); - /* Switch: '/Switch2' incorporates: - * RelationalOperator: '/LowerRelop1' - * RelationalOperator: '/UpperRelop' - * Switch: '/Switch' + /* Switch: '/Switch2' incorporates: + * RelationalOperator: '/LowerRelop1' + * RelationalOperator: '/UpperRelop' + * Switch: '/Switch' */ - if (rtb_Merge > rtDW->Vq_max_M1) { - /* SignalConversion: '/Signal Conversion2' */ + if (rtb_Saturation > rtDW->Vq_max_M1) { + /* SignalConversion: '/Signal Conversion2' */ rtDW->Merge = rtDW->Vq_max_M1; - } else if (rtb_Merge < rtDW->Gain5) { - /* Switch: '/Switch' incorporates: - * SignalConversion: '/Signal Conversion2' + } else if (rtb_Saturation < rtDW->Gain5) { + /* Switch: '/Switch' incorporates: + * SignalConversion: '/Signal Conversion2' */ rtDW->Merge = rtDW->Gain5; } else { - /* SignalConversion: '/Signal Conversion2' incorporates: - * Switch: '/Switch' + /* SignalConversion: '/Signal Conversion2' incorporates: + * Switch: '/Switch' */ - rtDW->Merge = rtb_Merge; + rtDW->Merge = rtb_Saturation; } - /* End of Switch: '/Switch2' */ - /* End of Outputs for SubSystem: '/Voltage_Mode' */ + /* End of Switch: '/Switch2' */ + /* End of Outputs for SubSystem: '/Voltage_Mode' */ + break; + + case 1: + if (UnitDelay3 != rtb_Sum2_h) { + /* SystemReset for IfAction SubSystem: '/Speed_Mode' incorporates: + * ActionPort: '/Action Port' + */ + + /* SystemReset for Atomic SubSystem: '/PI_clamp_fixdt' */ + + /* SystemReset for SwitchCase: '/Switch Case' */ + PI_clamp_fixdt_g_Reset(&rtDW->PI_clamp_fixdt_oc); + + /* End of SystemReset for SubSystem: '/PI_clamp_fixdt' */ + + /* End of SystemReset for SubSystem: '/Speed_Mode' */ + } + + /* Outputs for IfAction SubSystem: '/Speed_Mode' incorporates: + * ActionPort: '/Action Port' + */ + /* DataTypeConversion: '/Data Type Conversion2' incorporates: + * Constant: '/n_cruiseMotTgt' + */ + rtb_Saturation = (int16_T)(rtP->n_cruiseMotTgt << 4); + + /* Switch: '/Switch4' incorporates: + * Constant: '/b_cruiseCtrlEna' + * Logic: '/Logical Operator1' + * RelationalOperator: '/Relational Operator3' + */ + if (rtP->b_cruiseCtrlEna && (rtb_Saturation != 0)) { + /* Switch: '/Switch3' incorporates: + * MinMax: '/MinMax4' + */ + if (rtb_Saturation > 0) { + rtb_TmpSignalConversionAtLow_Pa[0] = rtDW->Vq_max_M1; + + /* MinMax: '/MinMax3' */ + if (rtDW->Merge1 > rtDW->Gain5) { + rtb_TmpSignalConversionAtLow_Pa[1] = rtDW->Merge1; + } else { + rtb_TmpSignalConversionAtLow_Pa[1] = rtDW->Gain5; + } + + /* End of MinMax: '/MinMax3' */ + } else { + if (rtDW->Vq_max_M1 < rtDW->Merge1) { + /* MinMax: '/MinMax4' */ + rtb_TmpSignalConversionAtLow_Pa[0] = rtDW->Vq_max_M1; + } else { + rtb_TmpSignalConversionAtLow_Pa[0] = rtDW->Merge1; + } + + rtb_TmpSignalConversionAtLow_Pa[1] = rtDW->Gain5; + } + + /* End of Switch: '/Switch3' */ + } else { + rtb_TmpSignalConversionAtLow_Pa[0] = rtDW->Vq_max_M1; + rtb_TmpSignalConversionAtLow_Pa[1] = rtDW->Gain5; + } + + /* End of Switch: '/Switch4' */ + + /* Switch: '/Switch2' incorporates: + * Constant: '/b_cruiseCtrlEna' + */ + if (!rtP->b_cruiseCtrlEna) { + rtb_Saturation = rtDW->Merge1; + } + + /* End of Switch: '/Switch2' */ + + /* Sum: '/Sum3' */ + rtb_Gain3 = rtb_Saturation - rtb_Switch2_k; + if (rtb_Gain3 > 32767) { + rtb_Gain3 = 32767; + } else { + if (rtb_Gain3 < -32768) { + rtb_Gain3 = -32768; + } + } + + /* Outputs for Atomic SubSystem: '/PI_clamp_fixdt' */ + rtDW->Merge = (int16_T) PI_clamp_fixdt_o((int16_T)rtb_Gain3, rtP->cf_nKp, + rtP->cf_nKi, rtDW->UnitDelay4_DSTATE_eu, + rtb_TmpSignalConversionAtLow_Pa[0], rtb_TmpSignalConversionAtLow_Pa[1], + rtDW->Divide1, &rtDW->PI_clamp_fixdt_oc); + + /* End of Outputs for SubSystem: '/PI_clamp_fixdt' */ + + /* End of Outputs for SubSystem: '/Speed_Mode' */ break; case 2: - /* Outputs for IfAction SubSystem: '/Speed_Mode' incorporates: - * ActionPort: '/Action Port' + if (UnitDelay3 != rtb_Sum2_h) { + /* SystemReset for IfAction SubSystem: '/Torque_Mode' incorporates: + * ActionPort: '/Action Port' + */ + + /* SystemReset for Atomic SubSystem: '/PI_clamp_fixdt' */ + + /* SystemReset for SwitchCase: '/Switch Case' */ + PI_clamp_fixdt_b_Reset(&rtDW->PI_clamp_fixdt_at); + + /* End of SystemReset for SubSystem: '/PI_clamp_fixdt' */ + + /* End of SystemReset for SubSystem: '/Torque_Mode' */ + } + + /* Outputs for IfAction SubSystem: '/Torque_Mode' incorporates: + * ActionPort: '/Action Port' */ - /* Sum: '/Sum3' */ - rtb_Gain3 = rtDW->Merge1 - rtb_Switch2_k; + /* Gain: '/Gain4' */ + rtb_Saturation = (int16_T)-rtDW->Switch2; + + /* Switch: '/Switch2' incorporates: + * RelationalOperator: '/LowerRelop1' + * RelationalOperator: '/UpperRelop' + * Switch: '/Switch' + */ + if (rtDW->Merge1 > rtDW->Divide1_a) { + rtb_Merge_f_idx_2 = rtDW->Divide1_a; + } else if (rtDW->Merge1 < rtDW->Gain1) { + /* Switch: '/Switch' */ + rtb_Merge_f_idx_2 = rtDW->Gain1; + } else { + rtb_Merge_f_idx_2 = rtDW->Merge1; + } + + /* End of Switch: '/Switch2' */ + + /* Sum: '/Sum2' */ + rtb_Gain3 = rtb_Merge_f_idx_2 - rtDW->DataTypeConversion[0]; if (rtb_Gain3 > 32767) { rtb_Gain3 = 32767; } else { @@ -2047,96 +2627,53 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* Outputs for Atomic SubSystem: '/PI_clamp_fixdt' */ - PI_clamp_fixdt((int16_T)rtb_Gain3, rtP->cf_nKp, rtP->cf_nKi, - rtDW->Vq_max_M1, rtDW->Gain5, rtDW->Divide1, &rtDW->Merge, - &rtDW->PI_clamp_fixdt_o); + /* MinMax: '/MinMax1' */ + if (rtDW->Vq_max_M1 < rtDW->Switch2) { + rtb_Merge_f_idx_2 = rtDW->Vq_max_M1; + } else { + rtb_Merge_f_idx_2 = rtDW->Switch2; + } - /* End of Outputs for SubSystem: '/PI_clamp_fixdt' */ + /* End of MinMax: '/MinMax1' */ - /* End of Outputs for SubSystem: '/Speed_Mode' */ + /* MinMax: '/MinMax2' */ + if (!(rtb_Saturation > rtDW->Gain5)) { + rtb_Saturation = rtDW->Gain5; + } + + /* End of MinMax: '/MinMax2' */ + + /* Outputs for Atomic SubSystem: '/PI_clamp_fixdt' */ + rtDW->Merge = (int16_T) PI_clamp_fixdt_a((int16_T)rtb_Gain3, + rtP->cf_iqKp, rtP->cf_iqKi, rtDW->UnitDelay4_DSTATE_eu, + rtb_Merge_f_idx_2, rtb_Saturation, 0, &rtDW->PI_clamp_fixdt_at); + + /* End of Outputs for SubSystem: '/PI_clamp_fixdt' */ + + /* End of Outputs for SubSystem: '/Torque_Mode' */ break; case 3: - /* Outputs for IfAction SubSystem: '/Torque_Mode' incorporates: - * ActionPort: '/Action Port' - */ - /* Gain: '/Gain4' */ - rtb_Merge = (int16_T)-rtDW->Switch2; - - /* Switch: '/Switch2' incorporates: - * RelationalOperator: '/LowerRelop1' - * RelationalOperator: '/UpperRelop' - * Switch: '/Switch' - */ - if (rtDW->Merge1 > rtDW->Divide1_a) { - rtb_Merge_f_idx_1 = rtDW->Divide1_a; - } else if (rtDW->Merge1 < rtDW->Gain1) { - /* Switch: '/Switch' */ - rtb_Merge_f_idx_1 = rtDW->Gain1; - } else { - rtb_Merge_f_idx_1 = rtDW->Merge1; - } - - /* End of Switch: '/Switch2' */ - - /* Sum: '/Sum2' */ - rtb_Gain3 = rtb_Merge_f_idx_1 - rtDW->DataTypeConversion[0]; - if (rtb_Gain3 > 32767) { - rtb_Gain3 = 32767; - } else { - if (rtb_Gain3 < -32768) { - rtb_Gain3 = -32768; - } - } - - /* MinMax: '/MinMax1' */ - if (rtDW->Vq_max_M1 < rtDW->Switch2) { - rtb_Merge_f_idx_1 = rtDW->Vq_max_M1; - } else { - rtb_Merge_f_idx_1 = rtDW->Switch2; - } - - /* End of MinMax: '/MinMax1' */ - - /* MinMax: '/MinMax2' */ - if (!(rtb_Merge > rtDW->Gain5)) { - rtb_Merge = rtDW->Gain5; - } - - /* End of MinMax: '/MinMax2' */ - - /* Outputs for Atomic SubSystem: '/PI_clamp_fixdt' */ - PI_clamp_fixdt((int16_T)rtb_Gain3, rtP->cf_iqKp, rtP->cf_iqKi, - rtb_Merge_f_idx_1, rtb_Merge, 0, &rtDW->Merge, - &rtDW->PI_clamp_fixdt_a); - - /* End of Outputs for SubSystem: '/PI_clamp_fixdt' */ - - /* End of Outputs for SubSystem: '/Torque_Mode' */ - break; - - default: - /* Outputs for IfAction SubSystem: '/Open_Mode' incorporates: - * ActionPort: '/Action Port' + /* Outputs for IfAction SubSystem: '/Open_Mode' incorporates: + * ActionPort: '/Action Port' */ rtDW->Merge = rtDW->Merge1; - /* End of Outputs for SubSystem: '/Open_Mode' */ + /* End of Outputs for SubSystem: '/Open_Mode' */ break; } - /* End of SwitchCase: '/Switch Case' */ + /* End of SwitchCase: '/Switch Case' */ /* End of Outputs for SubSystem: '/FOC' */ } /* End of If: '/If1' */ - /* Sum: '/Sum6' incorporates: - * Interpolation_n-D: '/r_cos_M1' - * Interpolation_n-D: '/r_sin_M1' - * Product: '/Divide1' - * Product: '/Divide4' + /* Sum: '/Sum6' incorporates: + * Interpolation_n-D: '/r_cos_M1' + * Interpolation_n-D: '/r_sin_M1' + * Product: '/Divide1' + * Product: '/Divide4' */ rtb_Gain3 = (int16_T)((rtDW->Switch1 * rtConstP.r_cos_M1_Table[rtb_Sum_l]) >> 14) - (int16_T)((rtDW->Merge * @@ -2149,11 +2686,11 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* Sum: '/Sum1' incorporates: - * Interpolation_n-D: '/r_cos_M1' - * Interpolation_n-D: '/r_sin_M1' - * Product: '/Divide2' - * Product: '/Divide3' + /* Sum: '/Sum1' incorporates: + * Interpolation_n-D: '/r_cos_M1' + * Interpolation_n-D: '/r_sin_M1' + * Product: '/Divide2' + * Product: '/Divide3' */ rtb_DataTypeConversion = (int16_T)((rtDW->Switch1 * rtConstP.r_sin_M1_Table[rtb_Sum_l]) >> 14) + (int16_T)((rtDW->Merge * @@ -2166,15 +2703,15 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* Gain: '/Gain1' incorporates: - * Sum: '/Sum1' + /* Gain: '/Gain1' incorporates: + * Sum: '/Sum1' */ rtb_DataTypeConversion *= 14189; - /* Sum: '/Sum6' incorporates: - * Gain: '/Gain1' - * Gain: '/Gain3' - * Sum: '/Sum6' + /* Sum: '/Sum6' incorporates: + * Gain: '/Gain1' + * Gain: '/Gain3' + * Sum: '/Sum6' */ rtb_DataTypeConversion = (((rtb_DataTypeConversion < 0 ? 16383 : 0) + rtb_DataTypeConversion) >> 14) - ((int16_T)(((int16_T)rtb_Gain3 < 0) + @@ -2187,9 +2724,9 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* Sum: '/Sum2' incorporates: - * Sum: '/Sum6' - * Sum: '/Sum6' + /* Sum: '/Sum2' incorporates: + * Sum: '/Sum6' + * Sum: '/Sum6' */ rtb_Switch1 = -(int16_T)rtb_Gain3 - (int16_T)rtb_DataTypeConversion; if (rtb_Switch1 > 32767) { @@ -2200,10 +2737,10 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* MinMax: '/MinMax1' incorporates: - * Sum: '/Sum2' - * Sum: '/Sum6' - * Sum: '/Sum6' + /* MinMax: '/MinMax1' incorporates: + * Sum: '/Sum2' + * Sum: '/Sum6' + * Sum: '/Sum6' */ rtb_Switch2_l = (int16_T)rtb_Gain3; if (!((int16_T)rtb_Gain3 < (int16_T)rtb_DataTypeConversion)) { @@ -2214,25 +2751,25 @@ void BLDC_controller_step(RT_MODEL *const rtM) rtb_Switch2_l = (int16_T)rtb_Switch1; } - /* MinMax: '/MinMax2' incorporates: - * Sum: '/Sum2' - * Sum: '/Sum6' - * Sum: '/Sum6' + /* MinMax: '/MinMax2' incorporates: + * Sum: '/Sum2' + * Sum: '/Sum6' + * Sum: '/Sum6' */ - rtb_Merge = (int16_T)rtb_Gain3; + rtb_Saturation = (int16_T)rtb_Gain3; if (!((int16_T)rtb_Gain3 > (int16_T)rtb_DataTypeConversion)) { - rtb_Merge = (int16_T)rtb_DataTypeConversion; + rtb_Saturation = (int16_T)rtb_DataTypeConversion; } - if (!(rtb_Merge > (int16_T)rtb_Switch1)) { - rtb_Merge = (int16_T)rtb_Switch1; + if (!(rtb_Saturation > (int16_T)rtb_Switch1)) { + rtb_Saturation = (int16_T)rtb_Switch1; } - /* Sum: '/Add' incorporates: - * MinMax: '/MinMax1' - * MinMax: '/MinMax2' + /* Sum: '/Add' incorporates: + * MinMax: '/MinMax1' + * MinMax: '/MinMax2' */ - rtb_Sum1 = rtb_Switch2_l + rtb_Merge; + rtb_Sum1 = rtb_Switch2_l + rtb_Saturation; if (rtb_Sum1 > 32767) { rtb_Sum1 = 32767; } else { @@ -2241,13 +2778,13 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* Gain: '/Gain2' incorporates: - * Sum: '/Add' + /* Gain: '/Gain2' incorporates: + * Sum: '/Add' */ rtb_DataTypeConversion2 = (int16_T)(rtb_Sum1 >> 1); - /* Sum: '/Add1' incorporates: - * Sum: '/Sum6' + /* Sum: '/Add1' incorporates: + * Sum: '/Sum6' */ rtb_Gain3 = (int16_T)rtb_Gain3 - rtb_DataTypeConversion2; if (rtb_Gain3 > 32767) { @@ -2258,13 +2795,13 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* Gain: '/Gain4' incorporates: - * Sum: '/Add1' + /* Gain: '/Gain4' incorporates: + * Sum: '/Add1' */ rtDW->Gain4[0] = (int16_T)((18919 * rtb_Gain3) >> 14); - /* Sum: '/Add1' incorporates: - * Sum: '/Sum6' + /* Sum: '/Add1' incorporates: + * Sum: '/Sum6' */ rtb_Gain3 = (int16_T)rtb_DataTypeConversion - rtb_DataTypeConversion2; if (rtb_Gain3 > 32767) { @@ -2275,13 +2812,13 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* Gain: '/Gain4' incorporates: - * Sum: '/Add1' + /* Gain: '/Gain4' incorporates: + * Sum: '/Add1' */ rtDW->Gain4[1] = (int16_T)((18919 * rtb_Gain3) >> 14); - /* Sum: '/Add1' incorporates: - * Sum: '/Sum2' + /* Sum: '/Add1' incorporates: + * Sum: '/Sum2' */ rtb_Gain3 = (int16_T)rtb_Switch1 - rtb_DataTypeConversion2; if (rtb_Gain3 > 32767) { @@ -2292,8 +2829,8 @@ void BLDC_controller_step(RT_MODEL *const rtM) } } - /* Gain: '/Gain4' incorporates: - * Sum: '/Add1' + /* Gain: '/Gain4' incorporates: + * Sum: '/Add1' */ rtDW->Gain4[2] = (int16_T)((18919 * rtb_Gain3) >> 14); @@ -2306,133 +2843,133 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* End of If: '/If1' */ /* Switch: '/Switch2' incorporates: - * Constant: '/z_ctrlTypSel1' + * Constant: '/z_ctrlTypSel' * Constant: '/CTRL_COMM1' * RelationalOperator: '/Relational Operator6' */ if (rtP->z_ctrlTypSel == 2) { - rtb_Merge = rtDW->Merge; + rtb_Saturation = rtDW->Merge; } else { - rtb_Merge = rtDW->Merge1; + rtb_Saturation = rtDW->Merge1; } /* End of Switch: '/Switch2' */ /* If: '/If' incorporates: * Constant: '/vec_hallToPos' - * Constant: '/z_ctrlTypSel1' + * Constant: '/z_ctrlTypSel' * Constant: '/CTRL_COMM2' * Constant: '/CTRL_COMM3' - * Inport: '/V_phaABC_FOC_in' + * Inport: '/V_phaABC_FOC_in' * Logic: '/Logical Operator1' * Logic: '/Logical Operator2' - * LookupNDDirect: '/z_commutMap_M1' + * LookupNDDirect: '/z_commutMap_M1' * RelationalOperator: '/Relational Operator1' * RelationalOperator: '/Relational Operator2' * Selector: '/Selector' * - * About '/z_commutMap_M1': + * About '/z_commutMap_M1': * 2-dimensional Direct Look-Up returning a Column */ if (rtb_LogicalOperator && (rtP->z_ctrlTypSel == 2)) { /* Outputs for IfAction SubSystem: '/FOC_Method' incorporates: - * ActionPort: '/Action Port' + * ActionPort: '/Action Port' */ rtb_DataTypeConversion2 = rtDW->Gain4[0]; - rtb_Merge_f_idx_1 = rtDW->Gain4[1]; - rtb_Saturation1 = rtDW->Gain4[2]; + rtb_Saturation1 = rtDW->Gain4[1]; + rtb_Merge_f_idx_2 = rtDW->Gain4[2]; /* End of Outputs for SubSystem: '/FOC_Method' */ } else if (rtb_LogicalOperator && (rtP->z_ctrlTypSel == 1)) { /* Outputs for IfAction SubSystem: '/SIN_Method' incorporates: - * ActionPort: '/Action Port' + * ActionPort: '/Action Port' */ - /* Switch: '/Switch_PhaAdv' incorporates: - * Constant: '/b_fieldWeakEna' - * Product: '/Divide2' - * Product: '/Divide3' - * Sum: '/Sum3' + /* Switch: '/Switch_PhaAdv' incorporates: + * Constant: '/b_fieldWeakEna' + * Product: '/Divide2' + * Product: '/Divide3' + * Sum: '/Sum3' */ if (rtP->b_fieldWeakEna) { - /* Sum: '/Sum3' incorporates: - * Product: '/Product2' + /* Sum: '/Sum3' incorporates: + * Product: '/Product2' */ rtb_Saturation1 = (int16_T)((int16_T)((int16_T)(rtDW->Divide3 * - rtDW->Switch2_e) << 2) + rtb_Switch2_fl); - rtb_Saturation1 -= (int16_T)(23040 * (int16_T)div_nde_s32_floor - (rtb_Saturation1, 23040)); + rtDW->Switch2_e) << 2) + rtb_Merge); + rtb_Saturation1 -= (int16_T)((int16_T)((int16_T)div_nde_s32_floor + (rtb_Saturation1, 23040) * 360) << 6); } else { - rtb_Saturation1 = rtb_Switch2_fl; + rtb_Saturation1 = rtb_Merge; } - /* End of Switch: '/Switch_PhaAdv' */ + /* End of Switch: '/Switch_PhaAdv' */ - /* PreLookup: '/a_elecAngle_XA' */ + /* PreLookup: '/a_elecAngle_XA' */ rtb_Sum = plook_u8s16_evencka(rtb_Saturation1, 0, 128U, 180U); - /* Product: '/Divide2' incorporates: - * Interpolation_n-D: '/r_sin3PhaA_M1' - * Interpolation_n-D: '/r_sin3PhaB_M1' - * Interpolation_n-D: '/r_sin3PhaC_M1' + /* Product: '/Divide2' incorporates: + * Interpolation_n-D: '/r_sin3PhaA_M1' + * Interpolation_n-D: '/r_sin3PhaB_M1' + * Interpolation_n-D: '/r_sin3PhaC_M1' */ - rtb_DataTypeConversion2 = (int16_T)((rtDW->Merge1 * + rtb_DataTypeConversion2 = (int16_T)((rtb_Saturation * rtConstP.r_sin3PhaA_M1_Table[rtb_Sum]) >> 14); - rtb_Merge_f_idx_1 = (int16_T)((rtDW->Merge1 * + rtb_Saturation1 = (int16_T)((rtb_Saturation * rtConstP.r_sin3PhaB_M1_Table[rtb_Sum]) >> 14); - rtb_Saturation1 = (int16_T)((rtDW->Merge1 * + rtb_Merge_f_idx_2 = (int16_T)((rtb_Saturation * rtConstP.r_sin3PhaC_M1_Table[rtb_Sum]) >> 14); /* End of Outputs for SubSystem: '/SIN_Method' */ } else { /* Outputs for IfAction SubSystem: '/COM_Method' incorporates: - * ActionPort: '/Action Port' + * ActionPort: '/Action Port' */ if (rtConstP.vec_hallToPos_Value[rtb_Sum] > 5) { - /* LookupNDDirect: '/z_commutMap_M1' + /* LookupNDDirect: '/z_commutMap_M1' * - * About '/z_commutMap_M1': + * About '/z_commutMap_M1': * 2-dimensional Direct Look-Up returning a Column */ rtb_Sum2_h = 5; } else if (rtConstP.vec_hallToPos_Value[rtb_Sum] < 0) { - /* LookupNDDirect: '/z_commutMap_M1' + /* LookupNDDirect: '/z_commutMap_M1' * - * About '/z_commutMap_M1': + * About '/z_commutMap_M1': * 2-dimensional Direct Look-Up returning a Column */ rtb_Sum2_h = 0; } else { - /* LookupNDDirect: '/z_commutMap_M1' incorporates: + /* LookupNDDirect: '/z_commutMap_M1' incorporates: * Constant: '/vec_hallToPos' * Selector: '/Selector' * - * About '/z_commutMap_M1': + * About '/z_commutMap_M1': * 2-dimensional Direct Look-Up returning a Column */ rtb_Sum2_h = rtConstP.vec_hallToPos_Value[rtb_Sum]; } - /* LookupNDDirect: '/z_commutMap_M1' incorporates: + /* LookupNDDirect: '/z_commutMap_M1' incorporates: * Constant: '/vec_hallToPos' * Selector: '/Selector' * - * About '/z_commutMap_M1': + * About '/z_commutMap_M1': * 2-dimensional Direct Look-Up returning a Column */ rtb_DataTypeConversion = rtb_Sum2_h * 3; - /* Product: '/Divide2' incorporates: - * LookupNDDirect: '/z_commutMap_M1' + /* Product: '/Divide2' incorporates: + * LookupNDDirect: '/z_commutMap_M1' * - * About '/z_commutMap_M1': + * About '/z_commutMap_M1': * 2-dimensional Direct Look-Up returning a Column */ - rtb_DataTypeConversion2 = (int16_T)(rtb_Merge * + rtb_DataTypeConversion2 = (int16_T)(rtb_Saturation * rtConstP.z_commutMap_M1_table[rtb_DataTypeConversion]); - rtb_Merge_f_idx_1 = (int16_T)(rtConstP.z_commutMap_M1_table[1 + - rtb_DataTypeConversion] * rtb_Merge); - rtb_Saturation1 = (int16_T)(rtConstP.z_commutMap_M1_table[2 + - rtb_DataTypeConversion] * rtb_Merge); + rtb_Saturation1 = (int16_T)(rtConstP.z_commutMap_M1_table[1 + + rtb_DataTypeConversion] * rtb_Saturation); + rtb_Merge_f_idx_2 = (int16_T)(rtConstP.z_commutMap_M1_table[2 + + rtb_DataTypeConversion] * rtb_Saturation); /* End of Outputs for SubSystem: '/COM_Method' */ } @@ -2447,7 +2984,7 @@ void BLDC_controller_step(RT_MODEL *const rtM) /* Outport: '/DC_phaB' incorporates: * DataTypeConversion: '/Data Type Conversion6' */ - rtY->DC_phaB = (int16_T)(rtb_Merge_f_idx_1 >> 4); + rtY->DC_phaB = (int16_T)(rtb_Saturation1 >> 4); /* Update for UnitDelay: '/UnitDelay3' incorporates: * Inport: '/b_hallA ' @@ -2476,18 +3013,18 @@ void BLDC_controller_step(RT_MODEL *const rtM) rtDW->UnitDelay2_DSTATE_g = rtDW->UnitDelay6_DSTATE; /* Update for UnitDelay: '/UnitDelay4' */ - rtDW->UnitDelay4_DSTATE_eu = rtb_Merge; + rtDW->UnitDelay4_DSTATE_eu = rtb_Saturation; /* Update for UnitDelay: '/UnitDelay5' */ rtDW->UnitDelay5_DSTATE_l = rtb_RelationalOperator4_d; /* Update for UnitDelay: '/UnitDelay6' */ - rtDW->UnitDelay6_DSTATE = rtb_RelationalOperator9; + rtDW->UnitDelay6_DSTATE = rtb_RelationalOperator1_m; /* Outport: '/DC_phaC' incorporates: * DataTypeConversion: '/Data Type Conversion6' */ - rtY->DC_phaC = (int16_T)(rtb_Saturation1 >> 4); + rtY->DC_phaC = (int16_T)(rtb_Merge_f_idx_2 >> 4); /* Outport: '/n_mot' incorporates: * DataTypeConversion: '/Data Type Conversion1' @@ -2495,21 +3032,17 @@ void BLDC_controller_step(RT_MODEL *const rtM) rtY->n_mot = (int16_T)(rtb_Switch2_k >> 4); /* Outport: '/a_elecAngle' incorporates: - * DataTypeConversion: '/Data Type Conversion7' + * DataTypeConversion: '/Data Type Conversion3' */ - rtY->a_elecAngle = (int16_T)(rtb_Switch2_fl >> 6); - - /* Outport: '/r_devSignal1' incorporates: - * DataTypeConversion: '/Data Type Conversion4' - */ - rtY->r_devSignal1 = (int16_T)(rtDW->DataTypeConversion[0] >> 4); - - /* Outport: '/r_devSignal2' incorporates: - * DataTypeConversion: '/Data Type Conversion5' - */ - rtY->r_devSignal2 = (int16_T)(rtDW->DataTypeConversion[1] >> 4); + rtY->a_elecAngle = (int16_T)(rtb_Merge >> 6); /* End of Outputs for SubSystem: '/BLDC_controller' */ + + /* Outport: '/iq' */ + rtY->iq = rtDW->DataTypeConversion[0]; + + /* Outport: '/id' */ + rtY->id = rtDW->DataTypeConversion[1]; } /* Model initialize function */ @@ -2523,7 +3056,7 @@ void BLDC_controller_initialize(RT_MODEL *const rtM) rtDW->If4_ActiveSubsystem = -1; /* Start for IfAction SubSystem: '/F03_Control_Mode_Manager' */ - /* Start for If: '/If2' */ + /* Start for If: '/If2' */ rtDW->If2_ActiveSubsystem = -1; /* End of Start for SubSystem: '/F03_Control_Mode_Manager' */ @@ -2535,6 +3068,14 @@ void BLDC_controller_initialize(RT_MODEL *const rtM) /* Start for If: '/If2' */ rtDW->If2_ActiveSubsystem_a = -1; + /* Start for If: '/If1' */ + rtDW->If1_ActiveSubsystem_e = -1; + + /* Start for IfAction SubSystem: '/FOC' */ + /* Start for SwitchCase: '/Switch Case' */ + rtDW->SwitchCase_ActiveSubsystem = -1; + + /* End of Start for SubSystem: '/FOC' */ /* End of Start for SubSystem: '/F05_Field_Oriented_Control' */ /* End of Start for SubSystem: '/BLDC_controller' */ @@ -2546,7 +3087,7 @@ void BLDC_controller_initialize(RT_MODEL *const rtM) rtDW->UnitDelay2_DSTATE_g = true; /* SystemInitialize for IfAction SubSystem: '/Raw_Motor_Speed_Estimation' */ - /* SystemInitialize for Outport: '/z_counter' */ + /* SystemInitialize for Outport: '/z_counter' */ rtDW->z_counterRawPrev = rtP->z_maxCntRst; /* End of SystemInitialize for SubSystem: '/Raw_Motor_Speed_Estimation' */ @@ -2566,66 +3107,98 @@ void BLDC_controller_initialize(RT_MODEL *const rtM) /* End of SystemInitialize for SubSystem: '/F02_Diagnostics' */ /* SystemInitialize for IfAction SubSystem: '/F03_Control_Mode_Manager' */ - /* SystemInitialize for IfAction SubSystem: '/Open_Mode' */ - /* SystemInitialize for Atomic SubSystem: '/rising_edge_init' */ - /* InitializeConditions for UnitDelay: '/UnitDelay' */ - rtDW->UnitDelay_DSTATE_e = true; + /* SystemInitialize for IfAction SubSystem: '/Open_Mode' */ + /* SystemInitialize for Atomic SubSystem: '/rising_edge_init' */ + /* InitializeConditions for UnitDelay: '/UnitDelay' */ + rtDW->UnitDelay_DSTATE_b = true; - /* End of SystemInitialize for SubSystem: '/rising_edge_init' */ - /* End of SystemInitialize for SubSystem: '/Open_Mode' */ + /* End of SystemInitialize for SubSystem: '/rising_edge_init' */ + /* End of SystemInitialize for SubSystem: '/Open_Mode' */ /* End of SystemInitialize for SubSystem: '/F03_Control_Mode_Manager' */ /* SystemInitialize for IfAction SubSystem: '/F05_Field_Oriented_Control' */ /* SystemInitialize for IfAction SubSystem: '/Motor_Limitations' */ - /* SystemInitialize for IfAction SubSystem: '/Voltage_Mode_Protection' */ + /* SystemInitialize for IfAction SubSystem: '/Voltage_Mode_Protection' */ - /* SystemInitialize for Atomic SubSystem: '/I_backCalc_fixdt' */ - I_backCalc_fixdt_Init(&rtDW->I_backCalc_fixdt_i, 0); + /* SystemInitialize for Atomic SubSystem: '/I_backCalc_fixdt' */ + I_backCalc_fixdt_Init(&rtDW->I_backCalc_fixdt_i, 65536000); - /* End of SystemInitialize for SubSystem: '/I_backCalc_fixdt' */ + /* End of SystemInitialize for SubSystem: '/I_backCalc_fixdt' */ - /* SystemInitialize for Atomic SubSystem: '/I_backCalc_fixdt1' */ - I_backCalc_fixdt_Init(&rtDW->I_backCalc_fixdt1, 0); + /* SystemInitialize for Atomic SubSystem: '/I_backCalc_fixdt1' */ + I_backCalc_fixdt_Init(&rtDW->I_backCalc_fixdt1, 65536000); - /* End of SystemInitialize for SubSystem: '/I_backCalc_fixdt1' */ + /* End of SystemInitialize for SubSystem: '/I_backCalc_fixdt1' */ - /* End of SystemInitialize for SubSystem: '/Voltage_Mode_Protection' */ + /* End of SystemInitialize for SubSystem: '/Voltage_Mode_Protection' */ - /* SystemInitialize for IfAction SubSystem: '/Torque_Mode_Protection' */ + /* SystemInitialize for IfAction SubSystem: '/Torque_Mode_Protection' */ - /* SystemInitialize for Atomic SubSystem: '/I_backCalc_fixdt' */ - I_backCalc_fixdt_Init(&rtDW->I_backCalc_fixdt_g, 0); + /* SystemInitialize for Atomic SubSystem: '/I_backCalc_fixdt' */ + I_backCalc_fixdt_Init(&rtDW->I_backCalc_fixdt_g, 58982400); - /* End of SystemInitialize for SubSystem: '/I_backCalc_fixdt' */ + /* End of SystemInitialize for SubSystem: '/I_backCalc_fixdt' */ - /* End of SystemInitialize for SubSystem: '/Torque_Mode_Protection' */ + /* End of SystemInitialize for SubSystem: '/Torque_Mode_Protection' */ - /* SystemInitialize for Outport: '/Vd_max' */ + /* SystemInitialize for Outport: '/Vd_max' */ rtDW->Vd_max1 = 14400; - /* SystemInitialize for Outport: '/Vd_min' */ + /* SystemInitialize for Outport: '/Vd_min' */ rtDW->Gain3 = -14400; - /* SystemInitialize for Outport: '/Vq_max' */ + /* SystemInitialize for Outport: '/Vq_max' */ rtDW->Vq_max_M1 = 14400; - /* SystemInitialize for Outport: '/Vq_min' */ + /* SystemInitialize for Outport: '/Vq_min' */ rtDW->Gain5 = -14400; - /* SystemInitialize for Outport: '/id_max' */ + /* SystemInitialize for Outport: '/id_max' */ rtDW->i_max = 12000; - /* SystemInitialize for Outport: '/id_min' */ + /* SystemInitialize for Outport: '/id_min' */ rtDW->Gain4_c = -12000; - /* SystemInitialize for Outport: '/iq_max' */ + /* SystemInitialize for Outport: '/iq_max' */ rtDW->Divide1_a = 12000; - /* SystemInitialize for Outport: '/iq_min' */ + /* SystemInitialize for Outport: '/iq_min' */ rtDW->Gain1 = -12000; /* End of SystemInitialize for SubSystem: '/Motor_Limitations' */ + + /* SystemInitialize for IfAction SubSystem: '/FOC' */ + + /* SystemInitialize for IfAction SubSystem: '/Vd_Calculation' */ + + /* SystemInitialize for Atomic SubSystem: '/PI_clamp_fixdt' */ + PI_clamp_fixdt_Init(&rtDW->PI_clamp_fixdt_k); + + /* End of SystemInitialize for SubSystem: '/PI_clamp_fixdt' */ + + /* End of SystemInitialize for SubSystem: '/Vd_Calculation' */ + + /* SystemInitialize for IfAction SubSystem: '/Speed_Mode' */ + + /* SystemInitialize for Atomic SubSystem: '/PI_clamp_fixdt' */ + PI_clamp_fixdt_g_Init(&rtDW->PI_clamp_fixdt_oc); + + /* End of SystemInitialize for SubSystem: '/PI_clamp_fixdt' */ + + /* End of SystemInitialize for SubSystem: '/Speed_Mode' */ + + /* SystemInitialize for IfAction SubSystem: '/Torque_Mode' */ + + /* SystemInitialize for Atomic SubSystem: '/PI_clamp_fixdt' */ + PI_clamp_fixdt_k_Init(&rtDW->PI_clamp_fixdt_at); + + /* End of SystemInitialize for SubSystem: '/PI_clamp_fixdt' */ + + /* End of SystemInitialize for SubSystem: '/Torque_Mode' */ + + /* End of SystemInitialize for SubSystem: '/FOC' */ + /* End of SystemInitialize for SubSystem: '/F05_Field_Oriented_Control' */ /* End of SystemInitialize for SubSystem: '/BLDC_controller' */ } diff --git a/Src/BLDC_controller_data.c b/Src/BLDC_controller_data.c index 8171ac0..f12473d 100644 --- a/Src/BLDC_controller_data.c +++ b/Src/BLDC_controller_data.c @@ -3,9 +3,9 @@ * * Code generated for Simulink model 'BLDC_controller'. * - * Model version : 1.1260 + * Model version : 1.1284 * Simulink Coder version : 8.13 (R2017b) 24-Jul-2017 - * C/C++ source code generated on : Tue Mar 24 11:01:08 2020 + * C/C++ source code generated on : Sun Oct 11 21:38:56 2020 * * Target selection: ert.tlc * Embedded hardware selection: ARM Compatible->ARM Cortex @@ -22,7 +22,7 @@ /* Constant parameters (auto storage) */ const ConstP rtConstP = { /* Computed Parameter: r_sin3PhaA_M1_Table - * Referenced by: '/r_sin3PhaA_M1' + * Referenced by: '/r_sin3PhaA_M1' */ { -13091, -13634, -14126, -14565, -14953, -15289, -15577, -15816, -16009, -16159, -16269, -16340, -16377, -16383, -16362, -16317, -16253, -16172, @@ -44,7 +44,7 @@ const ConstP rtConstP = { -9623, -10411, -11154, -11849, -12496, -13091 }, /* Computed Parameter: r_sin3PhaB_M1_Table - * Referenced by: '/r_sin3PhaB_M1' + * Referenced by: '/r_sin3PhaB_M1' */ { 15172, 15180, 15206, 15248, 15306, 15377, 15461, 15555, 15656, 15762, 15870, 15977, 16079, 16172, 16253, 16317, 16362, 16383, 16377, 16340, 16269, 16159, @@ -66,7 +66,7 @@ const ConstP rtConstP = { 15377, 15306, 15248, 15206, 15180, 15172 }, /* Computed Parameter: r_sin3PhaC_M1_Table - * Referenced by: '/r_sin3PhaC_M1' + * Referenced by: '/r_sin3PhaC_M1' */ { -13091, -12496, -11849, -11154, -10411, -9623, -8791, -7921, -7014, -6075, -5107, -4115, -3104, -2077, -1041, 0, 1041, 2077, 3104, 4115, 5107, 6075, @@ -88,7 +88,7 @@ const ConstP rtConstP = { -15289, -14953, -14565, -14126, -13634, -13091 }, /* Computed Parameter: r_sin_M1_Table - * Referenced by: '/r_sin_M1' + * Referenced by: '/r_sin_M1' */ { 8192, 8682, 9162, 9630, 10087, 10531, 10963, 11381, 11786, 12176, 12551, 12911, 13255, 13583, 13894, 14189, 14466, 14726, 14968, 15191, 15396, 15582, @@ -109,7 +109,7 @@ const ConstP rtConstP = { 2280, 2845, 3406, 3964, 4516, 5063, 5604, 6138, 6664, 7182, 7692, 8192 }, /* Computed Parameter: r_cos_M1_Table - * Referenced by: '/r_cos_M1' + * Referenced by: '/r_cos_M1' */ { 14189, 13894, 13583, 13255, 12911, 12551, 12176, 11786, 11381, 10963, 10531, 10087, 9630, 9162, 8682, 8192, 7692, 7182, 6664, 6138, 5604, 5063, 4516, @@ -130,7 +130,7 @@ const ConstP rtConstP = { 16026, 15897, 15749, 15582, 15396, 15191, 14968, 14726, 14466, 14189 }, /* Computed Parameter: iq_maxSca_M1_Table - * Referenced by: '/iq_maxSca_M1' + * Referenced by: '/iq_maxSca_M1' */ { 65535U, 65523U, 65484U, 65418U, 65326U, 65207U, 65062U, 64890U, 64691U, 64465U, 64211U, 63930U, 63620U, 63281U, 62913U, 62516U, 62088U, 61630U, @@ -140,7 +140,7 @@ const ConstP rtConstP = { 28540U, 25655U, 22323U, 18304U, 12974U }, /* Computed Parameter: z_commutMap_M1_table - * Referenced by: '/z_commutMap_M1' + * Referenced by: '/z_commutMap_M1' */ { -1, 1, 0, -1, 0, 1, 0, -1, 1, 1, -1, 0, 1, 0, -1, 0, 1, -1 }, @@ -152,32 +152,37 @@ const ConstP rtConstP = { P rtP_Left = { /* Variable: dV_openRate - * Referenced by: '/dV_openRate' + * Referenced by: '/dV_openRate' */ 12288, /* Variable: dz_cntTrnsDetHi - * Referenced by: '/dz_cntTrnsDet' + * Referenced by: '/dz_cntTrnsDet' */ 40, /* Variable: dz_cntTrnsDetLo - * Referenced by: '/dz_cntTrnsDet' + * Referenced by: '/dz_cntTrnsDet' */ 20, + /* Variable: n_cruiseMotTgt + * Referenced by: '/n_cruiseMotTgt' + */ + 0, + /* Variable: z_maxCntRst * Referenced by: * '/Counter' * '/z_maxCntRst' * '/z_maxCntRst2' * '/UnitDelay3' - * '/z_counter' + * '/z_counter' */ 2000, /* Variable: cf_speedCoef - * Referenced by: '/cf_speedCoef' + * Referenced by: '/cf_speedCoef' */ 10667U, @@ -193,13 +198,13 @@ P rtP_Left = { /* Variable: Vd_max * Referenced by: - * '/Vd_max1' - * '/Vd_max' + * '/Vd_max1' + * '/Vd_max' */ 14400, /* Variable: Vq_max_M1 - * Referenced by: '/Vq_max_M1' + * Referenced by: '/Vq_max_M1' */ { 14400, 14396, 14386, 14368, 14343, 14311, 14271, 14225, 14171, 14109, 14040, 13963, 13879, 13786, 13685, 13576, 13459, 13333, 13198, 13053, 12900, 12736, @@ -207,7 +212,7 @@ P rtP_Left = { 9790, 9433, 9051, 8640, 8196, 7713, 7184, 6597, 5935, 5170, 4245, 3019, 0 }, /* Variable: Vq_max_XA - * Referenced by: '/Vq_max_XA' + * Referenced by: '/Vq_max_XA' */ { 0, 320, 640, 960, 1280, 1600, 1920, 2240, 2560, 2880, 3200, 3520, 3840, 4160, 4480, 4800, 5120, 5440, 5760, 6080, 6400, 6720, 7040, 7360, 7680, 8000, 8320, @@ -221,8 +226,8 @@ P rtP_Left = { /* Variable: i_max * Referenced by: - * '/i_max' - * '/i_max' + * '/i_max' + * '/i_max' */ 12000, @@ -253,10 +258,10 @@ P rtP_Left = { /* Variable: n_max * Referenced by: - * '/n_max1' - * '/n_max' + * '/n_max1' + * '/n_max' */ - 16000, + 24000, /* Variable: n_stdStillDet * Referenced by: '/n_stdStillDet' @@ -271,74 +276,96 @@ P rtP_Left = { /* Variable: r_fieldWeakHi * Referenced by: '/r_fieldWeakHi' */ - 24000, + 16000, /* Variable: r_fieldWeakLo * Referenced by: '/r_fieldWeakLo' */ - 16000, + 12000, /* Variable: cf_KbLimProt * Referenced by: - * '/cf_KbLimProt' - * '/cf_KbLimProt' + * '/cf_KbLimProt' + * '/cf_KbLimProt' */ 768U, /* Variable: cf_idKp - * Referenced by: '/cf_idKp1' + * Referenced by: '/cf_idKp1' */ 819U, /* Variable: cf_iqKp - * Referenced by: '/cf_iqKp' + * Referenced by: '/cf_iqKp' */ 1229U, /* Variable: cf_nKp - * Referenced by: '/cf_nKp' + * Referenced by: '/cf_nKp' */ 4833U, /* Variable: cf_currFilt - * Referenced by: '/cf_currFilt' + * Referenced by: '/cf_currFilt' */ 7864U, /* Variable: cf_idKi - * Referenced by: '/cf_idKi1' + * Referenced by: '/cf_idKi1' */ 737U, /* Variable: cf_iqKi - * Referenced by: '/cf_iqKi' + * Referenced by: '/cf_iqKi' */ 1229U, /* Variable: cf_iqKiLimProt * Referenced by: - * '/cf_iqKiLimProt' - * '/cf_iqKiLimProt' + * '/cf_iqKiLimProt' + * '/cf_iqKiLimProt' */ 737U, /* Variable: cf_nKi - * Referenced by: '/cf_nKi' + * Referenced by: '/cf_nKi' */ 251U, /* Variable: cf_nKiLimProt * Referenced by: - * '/cf_nKiLimProt' - * '/cf_nKiLimProt' + * '/cf_nKiLimProt' + * '/cf_nKiLimProt' */ 246U, + /* Variable: n_polePairs + * Referenced by: '/n_polePairs' + */ + 15U, + /* Variable: z_ctrlTypSel - * Referenced by: '/z_ctrlTypSel1' + * Referenced by: '/z_ctrlTypSel' */ 2U, + /* Variable: z_selPhaCurMeasABC + * Referenced by: '/z_selPhaCurMeasABC' + */ + 0U, + + /* Variable: b_angleMeasEna + * Referenced by: + * '/b_angleMeasEna' + * '/b_angleMeasEna' + */ + 0, + + /* Variable: b_cruiseCtrlEna + * Referenced by: '/b_cruiseCtrlEna' + */ + 0, + /* Variable: b_diagEna * Referenced by: '/b_diagEna' */ @@ -347,14 +374,9 @@ P rtP_Left = { /* Variable: b_fieldWeakEna * Referenced by: * '/b_fieldWeakEna' - * '/b_fieldWeakEna' + * '/b_fieldWeakEna' */ - 0, - - /* Variable: b_selPhaABCurrMeas - * Referenced by: '/b_selPhaABCurrMeas' - */ - 1 + 0 }; /* Modifiable parameters */ /* diff --git a/Src/bldc.c b/Src/bldc.c index cf0c17c..7de76b2 100644 --- a/Src/bldc.c +++ b/Src/bldc.c @@ -166,7 +166,8 @@ void DMA1_Channel1_IRQHandler(void) { rtU_Left.b_hallC = hall_wl; rtU_Left.i_phaAB = curL_phaA; rtU_Left.i_phaBC = curL_phaB; - rtU_Left.i_DCLink = curL_DC; + rtU_Left.i_DCLink = curL_DC; + // rtU_Left.a_mechAngle = ...; // Angle input in DEGREES [0,360] in fixdt(1,16,4) data type. If `angle` is float use `= (int16_t)floor(angle * 16.0F)` If `angle` is integer use `= (int16_t)(angle << 4)` /* Step the controller */ #ifdef MOTOR_LEFT_ENA @@ -204,7 +205,8 @@ void DMA1_Channel1_IRQHandler(void) { rtU_Right.i_phaAB = curR_phaB; rtU_Right.i_phaBC = curR_phaC; rtU_Right.i_DCLink = curR_DC; - + // rtU_Right.a_mechAngle = ...; // Angle input in DEGREES [0,360] in fixdt(1,16,4) data type. If `angle` is float use `= (int16_t)floor(angle * 16.0F)` If `angle` is integer use `= (int16_t)(angle << 4)` + /* Step the controller */ #ifdef MOTOR_RIGHT_ENA BLDC_controller_step(rtM_Right); diff --git a/Src/setup.c b/Src/setup.c index d859c9e..435cd78 100644 --- a/Src/setup.c +++ b/Src/setup.c @@ -397,7 +397,15 @@ void MX_GPIO_Init(void) { GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Pin = CHARGER_PIN; HAL_GPIO_Init(CHARGER_PORT, &GPIO_InitStruct); + + #if defined(SUPPORT_BUTTONS_LEFT) || defined(SUPPORT_BUTTONS_RIGHT) + GPIO_InitStruct.Pin = BUTTON1_PIN; + HAL_GPIO_Init(BUTTON1_PORT, &GPIO_InitStruct); + GPIO_InitStruct.Pin = BUTTON2_PIN; + HAL_GPIO_Init(BUTTON2_PORT, &GPIO_InitStruct); + #endif + GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pin = BUTTON_PIN; @@ -440,10 +448,12 @@ void MX_GPIO_Init(void) { HAL_GPIO_Init(DCLINK_PORT, &GPIO_InitStruct); //Analog in + #if !defined(SUPPORT_BUTTONS_LEFT) GPIO_InitStruct.Pin = GPIO_PIN_3; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + #endif GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -694,7 +704,7 @@ void MX_ADC2_Init(void) { sConfig.Rank = 4; HAL_ADC_ConfigChannel(&hadc2, &sConfig); - sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; + // sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; // Commented-out to make `uart-l-rx` ADC sample time the same as `uart-l-tx` sConfig.Channel = ADC_CHANNEL_3; // pa3 uart-l-rx sConfig.Rank = 5; HAL_ADC_ConfigChannel(&hadc2, &sConfig); diff --git a/Src/util.c b/Src/util.c index 6111bd2..dba0146 100644 --- a/Src/util.c +++ b/Src/util.c @@ -64,11 +64,6 @@ extern volatile uint16_t pwm_captured_ch1_value; extern volatile uint16_t pwm_captured_ch2_value; #endif -#ifdef BUTTONS_RIGHT -extern volatile uint8_t btn1; // Blue -extern volatile uint8_t btn2; // Green -#endif - //------------------------------------------------------------------------ // Global variables set here in util.c @@ -199,7 +194,8 @@ static uint8_t sensor2_index; // holds the press index number for sens #endif #if defined(SUPPORT_BUTTONS) || defined(SUPPORT_BUTTONS_LEFT) || defined(SUPPORT_BUTTONS_RIGHT) -static uint8_t button1, button2; +static uint8_t button1; // Blue +static uint8_t button2; // Green #endif #ifdef VARIANT_HOVERCAR @@ -211,9 +207,10 @@ static uint8_t brakePressed; void BLDC_Init(void) { /* Set BLDC controller parameters */ - rtP_Left.b_selPhaABCurrMeas = 1; // Left motor measured current phases {Green, Blue} = {iA, iB} -> do NOT change + rtP_Left.b_angleMeasEna = 0; // Motor angle input: 0 = estimated angle, 1 = measured angle (e.g. if encoder is available) + rtP_Left.z_selPhaCurMeasABC = 0; // Left motor measured current phases {Green, Blue} = {iA, iB} -> do NOT change rtP_Left.z_ctrlTypSel = CTRL_TYP_SEL; - rtP_Left.b_diagEna = DIAG_ENA; + rtP_Left.b_diagEna = DIAG_ENA; rtP_Left.i_max = (I_MOT_MAX * A2BIT_CONV) << 4; // fixdt(1,16,4) rtP_Left.n_max = N_MOT_MAX << 4; // fixdt(1,16,4) rtP_Left.b_fieldWeakEna = FIELD_WEAK_ENA; @@ -223,7 +220,7 @@ void BLDC_Init(void) { rtP_Left.r_fieldWeakLo = FIELD_WEAK_LO << 4; // fixdt(1,16,4) rtP_Right = rtP_Left; // Copy the Left motor parameters to the Right motor parameters - rtP_Right.b_selPhaABCurrMeas = 0; // Right motor measured current phases {Blue, Yellow} = {iB, iC} -> do NOT change + rtP_Right.z_selPhaCurMeasABC = 1; // Right motor measured current phases {Blue, Yellow} = {iB, iC} -> do NOT change /* Pack LEFT motor data into RTM */ rtM_Left->defaultParam = &rtP_Left; @@ -466,8 +463,8 @@ void adcCalibLim(void) { // ADC calibration checks #ifdef ADC_PROTECT_ENA - if ((ADC1_MIN_temp + 150 - ADC_PROTECT_THRESH) > 0 && (ADC1_MAX_temp - 150 + ADC_PROTECT_THRESH) < 4095 && - (ADC2_MIN_temp + 150 - ADC_PROTECT_THRESH) > 0 && (ADC2_MAX_temp - 150 + ADC_PROTECT_THRESH) < 4095) { + if ((ADC1_MIN_temp + 100 - ADC_PROTECT_THRESH) > 0 && (ADC1_MAX_temp - 100 + ADC_PROTECT_THRESH) < 4095 && + (ADC2_MIN_temp + 100 - ADC_PROTECT_THRESH) > 0 && (ADC2_MAX_temp - 100 + ADC_PROTECT_THRESH) < 4095) { adc_cal_valid = 1; } else { adc_cal_valid = 0; @@ -477,12 +474,12 @@ void adcCalibLim(void) { // Add final ADC margin to have exact 0 and MAX at the minimum and maximum ADC value if (adc_cal_valid && (ADC1_MAX_temp - ADC1_MIN_temp) > 500 && (ADC2_MAX_temp - ADC2_MIN_temp) > 500) { - ADC1_MIN_CAL = ADC1_MIN_temp + 150; + ADC1_MIN_CAL = ADC1_MIN_temp + 100; ADC1_MID_CAL = ADC1_MID_temp; - ADC1_MAX_CAL = ADC1_MAX_temp - 150; - ADC2_MIN_CAL = ADC2_MIN_temp + 150; + ADC1_MAX_CAL = ADC1_MAX_temp - 100; + ADC2_MIN_CAL = ADC2_MIN_temp + 100; ADC2_MID_CAL = ADC2_MID_temp; - ADC2_MAX_CAL = ADC2_MAX_temp - 150; + ADC2_MAX_CAL = ADC2_MAX_temp - 100; consoleLog("OK\n"); } else { adc_cal_valid = 0; @@ -865,6 +862,19 @@ void readCommand(void) { ctrlModReq = ctrlModReqRaw; // Follow the Mode request } + #if defined(CRUISE_CONTROL_SUPPORT) && (defined(SUPPORT_BUTTONS) || defined(SUPPORT_BUTTONS_LEFT) || defined(SUPPORT_BUTTONS_RIGHT)) + if (button1 && ~rtP_Left.b_cruiseCtrlEna) { // Cruise control activated + rtP_Left.n_cruiseMotTgt = rtY_Left.n_mot; + rtP_Right.n_cruiseMotTgt = rtY_Right.n_mot; + rtP_Left.b_cruiseCtrlEna = 1; + rtP_Right.b_cruiseCtrlEna = 1; + shortBeep(2); + } else if (button1 && rtP_Left.b_cruiseCtrlEna) { // Cruise control deactivated + rtP_Left.b_cruiseCtrlEna = 0; + rtP_Right.b_cruiseCtrlEna = 0; + shortBeep(6); + } + #endif } diff --git a/docs/pictures/paramTable.png b/docs/pictures/paramTable.png deleted file mode 100644 index 16550a6c39c3e25c824f64cf3af5c4394f7b631d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63028 zcmcG$1yGy)*DV@KDFq4?C{9T!?(S~I-Mv6@hvF%;XwejRhv4pB++B-1#R(exqP0LR3K%0H_3`-5VppU!yom>$m^_7+rrJ2z?F(p8$Z%0T~HV zbq~YChmj$Jp|jnPBVj2-g@Ay^XPD_(=2d3j7{m4JI$qW*m_<_n z5Egs@z_ttPhHF?1>O}n9;i2ydCLD3z@1T|lzrAk#KezkUKX&=Tz?%YRix+sqmt#*l z+GoNK#pO-D-^d{Vz)v&Y_p3oVEimcA(pujuBksMF^IhL_W`ETF>ZG+&-=~wOO`bEZ zne+$zr;9PVUnV24r$xBZhA z0MO@`+FE28q8Hj~Ju`Zu_rlRT4q5&3)Fb?WZx_nHlabFyRiiuzdT>~D(dYPqmNq|G zZ?U3Q{>>*buU8Re<+lFmcvb5$?CH#AV=Ce4uJ36v|LNTK(f2{v2PO=&kR2T?J!7)!aG0NTtY4nS}1~HpDgxq%E3v zt@+}*_XXac`{I#)E^$^7r>cVFS_n~wg%+Q(0sxL!k^S|?@miqV-CI{WoN7jTDs4YQ zV)DrXQnhx5UJBB4hE_P&to_O8q5O%vNVo!&ayC>o znVNml@`6~rV8fre`$Oo=RO}9a*QLdp>dx8cNKAUX*~$eC?ADMP@_8xR3|_JCs*leA zU#ndt+R&@<9y_gubXWst@a{D53<+Y+Go^DFsUandDN$~%#%V;}lpY60Pnb_-yS|U@ zFr%XM?lZf=uoqoUx1;QRmb|u~2wqce;YOsyK^n@05fj)F%GuemelaRwElyMpMjR$e z^JjmVj(4d2{(1&OHy(b*E&iT?M&Co#b*q|fwj`N^-Yo%|NlW6XXsS#0PYahpf{=~P z_NO`cmL00Ms%<~wu>x7hdsE&=!~1Yk?r$X9?o=JkF$W)?*pBW@BT;w7@Fyr1I+GH@ z6Ah=aS^&*9GyE+6-G4R}FzFk5^zUOIpzGlSp31o@@i<44+lgP<4_R@6Pq4Wsx75Hz z4g>W8%eu{6Xe+BmY)g1d&P@deJ^H54)|kbP7<>vbOslZ072f$}JfwjGH@aA&_>h+0 zY&xQBtAGFirjb9pNS9g2+Wgf~#zQ?>eXl-*y->KfA8c-{qNnms0khQn^n$gXN4~gH z4}Or_pW1!-Bb`#JdIyn)oU)7vRtZh zhnUgYEt3gtJ4;|vn@NQ{1qm4jRt!*=(*Qdz0=$6;aJ2ffk?@#>eqLg?Tt3~LJdMCl z`!e2x1BRRw#fkKkD`K^-IfI*vStwRC-c!UyQW-ub z`#AD5yTrhaO|F+K$=k;EQ}-4K_n6A05Ln{2@o=0d6amnnq0aP{Y&d(vp9ziQpQ}cJ zC=~NQPl^BAQ(U0$&82&Vu%EjIrZ!*)-jfj#Xr-QGiXwsw0^p~4CTyOuK_UM?mh}*C z38MB>9{{Kzl)?qBu8^ktG-{=-4Qe+l__q3bWxmk*pbWAd-qi~3Dh3we08XVXd-@)N z@q@b-$2K^ZmE2c7l%DtWF;+OIyr5=tpHisUnIa$yrUv?4rd76jJn0=I#ERu}P<98X z6A^pjB{o*o@tqBr^i5ln*9mejto72SuVd@2^&m@Pp<)3@aqbhqKzBNsfjgOt99VXKI|r1^{qzxZ(W1bK?lPEk8mHognEUFqbAlu;P=ytOowRXeVOXi6 zWIu#3JgV}8gf9X7L03@loXF{ueV`%Al*+@zmna@{G`@J%d?Iq(0=sf$+T%8IsQgliqDihKZ~6?Pe)1i#8)1;h zG%L`?xqBw9<~$skc#B?j5ADe)JREK8WrZB!8K+%7n?jAXv8rbI9g3-1SeC9~{UPP$ z$GX~@?d_Z>EhU#ZIh1rk-F0k@?Q}*{25?_vor&lZ z2_2{cPZhp*%SbNq6?K9(5@H5<&Q|s_KdVipO4ADnY6Li{W0lYCyK$T zLGsLt;vRB0atZm+@=aIn7|&_)!V3B>p_%0iw4<|j2{dV$R147T>06j^9A@LFpG=8- zdz21kWZ-RLoY)7D@kZ#-a355NrHyW@rzl&5h-9N61N3=|V3s=Xa$k6kRJ@wR&K^*X z&wZTDJC!w%r>Y%5n9T1iOHr|AGEmFx39@)K)9qjIBAA9yPJ(IHOO`vD1auAu}kiAnzM z;-~el=@7#xG-w$%JM+=2952Lu*>Cp@U?1ED`yTT1Q87mM-aO|7C9+>uj*zR48rZfp zbFaG6yN$=hUZL2mFi?@_WW+*Um-6%KnMOv-cKB*`c6%@n^o0qdBED1hMPW5pv+m&r zxt0B&8UMvdUw4TAdS>Ciy__&L<-2vgIWW((P6Sc57?q{uu*0wKRig+>?v}kc>#R)a zKotKB*>gaHYWN1?A>u&-=GrqC19tVP{!S!e4}jy;e;KPXLMXe;eJvs!FL961_5?rD z3UN{d(yx=*PZ49FyaCQdz&3Fy2m$tQ@6Z05u~UX(O)?Svb1iU1go4{2kANS2pPv+w zRse?KC^+TYhH3p8SK71x6GKTOc)WCf*k|?I*d%K3b>V5bDdZD` zyg&q$g=&KCANRJ`Pmc{-Aa{G0?kg^oTVZMkR}X1T3Y!p&F`I>uU!}>WBoc-VJm^*<+8Bx8BX&yhoD?QT^L?Cr2 zYcVNMiM6G!fQY@B1R&Dkdjq@CHKXwqHo*BTDB%65n)dVq%dp*3i_eN5-d=7LjgXh0 z3w2e#o%~?GxY$myw(8090s5ExP;l+S8Rn9DU@2O{j#3Bi|Dm{I)B!9fFqQre= z7~k+2xq)zHYcpnuEiF>;(%ULhVxu{qc$B#blA(;>G1EDm-;O2FbUT_4N z+tFm2+GiIng(poLro2s5&l2qz?L2QRw`QjFbwDMfj1qIdiTi&GSmT@Xn9=aY((3Rm z`ZT>gSlaH`_%)xy@6oTU>)~0Jyyf$_)cbkJNyTK3sU@L=JG-$kT{~P;}0{Gn3dYtnO->o9jIootj>IGewwnkM>_MS!?fFiX+_X>q9j zp|>beOt=vfJKPS-M%Gd$gz#A1)_BZMyMKYQzBY)0n_zs64?1 zU#MSg#BqU)8(n+RbFa`IynfgQMZUhQrwU{?Fb!#vkg?F9EG3Qr9rj4QgS3nXD2){7 zwQ;t*i;yub+KfM95bHc1zC9f^OS0&t5yH!{5%@}dB00s-w92nZ=_R#=|Im zVwQb_C`FS&Vm&7G<;!wfal_J@86GC7(fflBg%R~5WtH?<%aBj=ldr_F7?TzZ9m9WR zXQL5_%0`y^<5H>?iBRiXkpr=`x$!tJR_!4%1TAMGU)3+??%!I{bc;Q_!;#N@8|Ll1^;lH_*aCevx18d z+jFZOk1tm=1V1ADy#ukQ&%VQs59$BVVZ_%iUd-L)LyguwZnq8Fy}~nL4KIY+`A7^O zl+#Gn{1E_JlJr8y!Yw=`D?WJTdp=Efz20U14i14u?O!~dJ)n>ETwkju*XcM{f5a`S zFZ^Jr(+uo>$qNU=#V6qk4I-+jX_K+9W45}ZqAb28(c2Vn1~a(HmvWgbhKcNE*W!S? zCYlqIrTxKlLgq7@o3uf5cp9eW3B)Fhr5cu(tigs7N`O&>r|r$YG*nAhg0k-(f?N6` zV`rhL#GX#q)`D4wDVH0j@99*H@;YbyI#$k8k9m;Gv4tS-O6QkC@+u-Bf~gd~y${>*_Pa-|NYC ztj`CO^!4V8ODb4&O*<=Y#kCn-TFA2HaF1u3YTLDP2O-7Z@8ZQ_;?Yf;fy%uJ~?1XBJUk9rc$(@JN@nFqO0-NBIoy#$c6fdP@YSjlBh_N=oqkB zbl2o6xcU7z*IA3UR5_CS_h}j{z)`(aeu__hHH+%oh0oii?kLRu;CPbj+`pd1GTT`# z1f5!L@*F~X7z!qmo=*CoLA)8XlCS<}d3N4tj+=3iT2QojQgmSTQGQCpr~xTMdW2w; zfAFikz=Yi*nd99tJNbGNe9HLaPVWIP3H@nlo49v$L<%0%$~CwTn+MM-SofJztNi?p z6zLqdTW3TkjFcjIYK%>M0Rg9p;3lJ%wZzNkO;iER~* z_RY+hCZt0e>bC5$s1-8sFr6FGrtpCb`u?IDig^=kHV7q5MYTEWiDs7eStlqJImRq) zVMs=L2USNg+Lg6|9lDDfer#+%{oN+}P09$mjNzs|Hywnpq0|RPn;rTQ7tSKbQvE~L zWWLf6ag9v5M~dH+%zB%%3qxB_noB%5<5n-GvkyZ?K+8drPYpTx?X=X(W(Ajh6b0C{ zyy_oPa8`nYdlvVB%A}h8po>4jES)e1R*+y;i_5;?0bpMYW#pIY;s`swj@0N42Nj5c6!g$n*VnC;@}87{Mj8Jy z;!~lZokRPyVm`L-_xNug#fkRo-q>1n(Fr+Uyx80-)yVnR34P(Pt^Vy}VIRob^zOK{ z8*c7D7ZW6(hB)7!ear%*|I*}L6TR<{I{9=OVW*$31unX!g}Nsc%JilYB#j}#I$CLm_YhfmTN7OG6!i7n|7 znOq&Rzo17d-M9iG}dJ?~=s9u9qUvU8pMw7CQ)^}r4~-$#Df+xyVdg}~=C z(8mBk`n3%vjj$|fG1{3m(0=al&Mzf*=JywAHo_5`05 zxPI87o|dqV;~0${?wj7RpT(j1;#=?!iu0j_-)t>zH;=I}Sbjl})m;KcI4X z#R=o3B$_6tAAaVb3?!=g?6s{oCTHXNRi8se-Ya_!Fi(;L)6OTQaO}};2LTeKjLSR_ zLk@rd0O_+gz-FYLzBhj*=-z+$OKtU|Vp|7x^Y$MObA|s$)1D8{3B`0o`!7C{xj~+5 z@E^g)jtDO8JS+AnvJu6~@e_G->}oby~~JaDU> zI!NioHBV45vk;9XMp(6G zm4=YBu2>@O0(qN`7M$0NHQ${@wN#iF{}A_=)F4twt7J?ah{ls69_XQEi5y+1W^qa5 z&HiB9jN6ww&VK$o6dY4l98$X#l1>%qZp$eK+kf!Pt@izP_sCNT$zsYf{?VwTy1R&Gow%~hH(&m}k(}(d4Ci|mD>Q%=y z9=p1kXz^<8uf`Ce(suSHk_P}t03=rol3`LevLO6^j!Hz{T7vuQQR z>2B-KFigIH#tE)peYTV4iwnPH(Iy4Me2JiS{6z0p&Koh5_Z9dbachxSOdUCL>JQW>-7XD8!tj0en(#m@GvnDpQ>86`T;QGl+oX%7nUV{#xK z${R1Ryn{}t2CDaDKtSkgGh*d}b(CBmt3{@iZ&sMVfHr^BsKkvCB+#fpqq>_uh+B?l}&}6<))Zo?DA*JJWy6}Zh z6XLT?R|vAzo6&009m?VqX$q*67!|1?F?rP`KTGwa5$dNb9U#EIz>ovtZx+@vB=PlF z(XMD<4R6K1+(et%&HnJV9U_8voY9*Svg7j#vd6EHZqu)&Z%@4Qde)5|~@e z2D>v239x^FIzhghz=;JF%FND4B1GqNJA3{6KoV~;*ZEj*3H13|jV^NGg_gp{dLW*3`4->=>xmWgxw8igjdq(nRtB8#_Hr$n$-N zYk^>lUc3o1I*ocM4LT#DEa$#+Sh^Vm(AO1;d91}IcwL$8uI(I-qg3~asDx<9$<`Gw z;U6q zDS*{uOJB#pW{P8({8x%om7cV|4bYUGCn%?YkZ=|s6|`(1+A6%5RxGIXf^1EFT}Yna z8K2oM+MART^ci8^{|MPz$+nGe|1sSMq3zOg$ba{G1Qvx%c7WeB;-J%gRe+F}g{m5B zB~thSw*VjerP^21$}mjlT!-7O3SE?Ff0rd5=qFjoCEweEu}PB&NRBjk8ct{o8neye>6q(^k%LdMCPz-IX*yi(FVhy@y~#w0LL_ z;i7U-|2j;Y9y7<>s>k96EvjchERZFWR)%UYs!I!V%!@pTs!obQVTrMt6(O&JT7i&` zToTEvRt@|`m1InIq@xm!*vX!Ht`4W>=C;4h>QDUh$#JH5k4OgwL^7C|hQ8?V^%?sN`8G%DPRL4>2zwu`` zK6C5B7 zpnqk?1ouWF_;D>Ok+gxX3XVjg$qny1C>Fk+QzJ3);K1cSv`{cDJa!X!&!#{nxbNQJ z;-ga6zUptxhp3qGreRH=0UvmX%rrYG%;`Vvwk^Yrgl=n&=ZS0 z( z@+-_}aYjhw+h9CE=I(tDGG)}BSZ;3CWI6~o6M^882}=}93gfnK%IUm&wdCv3!T6+X zEdl==8u$kXhJ$bdm>+`?ATkzrf96!Th@}o^=vl)vgGNo{z&0XyNWkB@ZNr}u{S6Qx zKzF;b*=KOu8WPbrPgWlZ38p0YWw=-ynA` z0V~y&?G(^&K2GAN7CSGe_|xgjzvpd`fA9z$%jsHNXfw5F^17TboqU<~;m(+<=#xS@ zkKs9o{Cvq2Ou_SiXS`IN+h)u%` z@BENF|86^{jV^s=R_|bUG>=t4pv2P3`Gx+?_%J>&yh+WTk8q{;N|0Yo_!>XUehKp7 z2UWoQ6#K>C#lp0XOQ#i=z!sep;oqk4fr_YT1+jgT2ukmvdMb8SEpbH`lPKI|x+dSu zD`DS(aX1Gofr(dvNDaybR! zbbo3oJpyK90IX>?ZZQJ|>Sv+v=`~QSt%|Fej6;#$COmC-Rka+w?Tef1R)uzOxdxq< zEnXiDd!2RXZHT{Iuh}CUvvIK)LCKFgU7OZ;|8GYh)4+MeerLLh0sqZcH6 zIv9)vpUquo)y?2vyw6oDKztX*|Kc{uWs~5chwr0zpVKzyIv$X<<)Du}z+kw zV1-SpB8DJ6@Oh*C9&5{vmE|#Op&cbEB(DB-&aZDggB5_UdT0`@cTOws%MH0KkpJEL4~I^sN5u@+ApcvqA@-1uK5%o!HL`z+rf480PKm`*vco5dD{L zfNH5d`Y%t=5W1dKuxo~4URAT$P^W^RrVMQT+agfbo}}Tx)3( z+@|s97oQI zCS?g|ERRl<^}gCu;$7Pjg|fn@%QB^eaw?6o)Ai{W4>(Nf%ENQ1bvV!{BNJ|i9XV4q zLGn9=m(%hyy+dH%ipTN!*muTlvMkrGb$2jp_%{U72}RO>m?OVeJ)})vhJP}n<|a}c z|Epduvye|)^}A)F_{(6N;k?^%lH z%SD=3*z&d`MhpomoG}y?qaXHb7(RY)b!*z_x+pRIknh_))P@!$c95mbC^Y(Josdt| zl_Jm#S4?xmjoz-i6WWO6dCXiY>$u!;;oc{4Q^J`-v7?z98lQC)K#1f!14Tv`!t@Htkc3M`TL6+PHhtYI(x0Xy@OUgX4Pf8r8C+*uq9Gyf?htY~-}{ zEiqVlALSBF%HL{$w9_LVmcr>D$PL{LJ`!GqCejI|wx0VeR1vNdHa%5o_&!}6>qLB* zJt<)$-AaEx_g2>Tj^R{<4u?L5zDx@3QYiq~rJ%f%O@H?ckeU!E>}Hie(aXOWD|pjQ zB^5b<61bL43;VgfNd4I}7_r8=}jm#gR3djTAC%9Q7uEzM7l$M>Sg@Hv^dxb8jua+#8BRGD?9 zirl=ziEq-cF+WS-Ibe(7?cq6ADSXt5vaykS%uGx9U9 zopsi+6%Z^O(M^-5mpiPj)&_Nh2hm&;=Y)66#*iS!<-s9FLW&Wm@;ckQ2P~BR0^UEG zvGv_K9+p`(X_b?VoCI~X-xE2BiZ7(v*f2IVFav%zHjXm`8IIVNSknrA#CAO~4oWDr zRnx9ui$=0iorJL|>Pgzo?w9EPGAU0RdO9=yWjujo_sZoujztHg?G21{oJjILe@TV< z0RwVeO082<@zPmKY3{9pufwZ>l2RO@=8X-*!KI|r&5AEb3;Hhqj&x)7=A+cyPyR&} z#f)Y|TX|_3GkLx%5M%UxG-U$KDesfNwgpPOre*29zKhP%JGE%ahJeEo;+h^q{vud~ zzz{myr107{E`BWQ((+t~1a$q#AY3Q>^p!zz`D%-NJc^4EJTN%oQxdpmtT4vM)47y& zWtkBOF&^6reKZ`F$em_482@;OTGRON9w5{Jil%D%kYgA* z;`A*tmEITvdkOOfhMvmTXgDDogzlm{EBPH@K%O=d7s3@r$_Y}I!rqq2w{kFmGiPny zcZHAD;u$RC1J+Vc;UQyGpAqy@38MZ>-U2D`dCy%=iUujvp?S+mYbd&93k35Lf6u<;1ci%{SZ z1CO)ygnf!2lf>+Vg%*=Gdf%nDhAmGDu0;B?JNWD{&T3a^l)m=D;+W?!tDN41ayENC zop3Zs>Vk~@Xt8Br*A1`68Sfvf$ToL*SO0B;e8t)VJiM80U?nCtO2WR;cDSt6Y6>Bi_6xzW?Do5QQfv<{BbJZicl~W4k!(CTt}eT`aNM}R zM*tbngADogezu*$&pp9rhDtK|MvzS?Iunf} zqxMcys_zuGStzlG=O?QjIw#N+9hP}upqKw#Y2hQZ;`2qJC9gmK+ogs=VPF#Ysq-7r z>NKc^IQiAfEX65W4lQr4*B`uOz5Yz>_@rj%D+#dlR0P>4=b9q>SHzkohV)|L-xcEJ z#{}m0C-t2*R1ZH-?x4M}t$=QAL$W@utQq_Bh0ZS)OW^}KFLJ7vPa`7d96W8ExKAHX zmo}mUa<{uDJ2fP~pV>r_gP4V@EUsxL38>kFH1i9VFP7?Ma3w<}gfbqx94NHg_OlwfUhs;>ZZ zpk$(0nJ&)Q8ug29q+CFr#=(qB0@qdo_r`*|=JG8){K+4` zSiW*G7;iWIwp%*+ikS6q&jZwrg=X!2JB=`65?7gqVZStIv_#Xo6PKh=D%D(R^rc>g z40L)6dDT>};PZ8l7ANPcLROy6ruQ)U?g@Le)yTeqZBNAs#vGeMtc{F4<#y)JL9PVb zHj|$c#6SsGgsvpE250E>lFi3P*pGa5QKtNOZhfJuc)<>R+zcC=AQ%6j!$n=U6qcr! znuOO|d$2**#`>~_=38xxxJSN9A=oU7dv1g$23{CAyN*SUaOcuRYt(MM`W)9d>A?B% z^3{9t5j{!X{)+tA)$XQ90@cM;S91*w^CT*P@`$6~Mg$CTpGRoSxME_?8{Bd%a zL=}_0Qvgy#KOKKG_h$2U!^ns292K!pzg{kS_ZCwlYRiV=WDrq_Zd4(Oa+g8xmo6PG zuoiH!(q0h7bqduuB%_$I5525*ny|zm&Se_EVjGR`1z`C_ zj^Ym@GfUM$jX6OzT~-B)(`UAa%w>eXcgs>2GMBWfCvlDEtntrJwAXlxyNw%-xcSXDsYZ0v-bMLQOQbsk~+#J+t|`EERalZ z#o)Ad_s^VOQ&I$I1k@M{=oR{y^I;LJd^S!hD8j0=vpLg0J#x=_e|Yjd+SFzBD@d}H zkKGog4FMWERvFKx5^iZK_wFToDoJrWkZ+2DVYIi;e^jq57DhYw$ zfx}7E8Dv$2sL|*-Ih%D!7t_rrMnsn)Xp{}HR>>{PNJ0sg-g1=buv%1o;qI@dFZMX~ zMnt|I{+%X+vU7gt;wnpU_&*xBu`Ocx0?7bo&3-)zol zTW?A+d}P|%H=4`4FtIU&Omkrm6ce9Z4{=V2711{AEh$Vaag|^P)R60M4+Ub66x}m= z$EQq^^6oHgDdc&T8ndT`8uv{vEz9WIGK@Vh!q{k6z>$+fE=(g;0i9~1_iL#WUpr*$ z`0K5^^Z!K&ZYh4Qa8<`MZX;*!`rilS<|4RiE@~{+JPs{^kRnPyEZkmv}Kc1tT2sgT~L4{>q4qo zhxpeGQ&hN+p`W~`ce5eTv`Sot{3jFbZ&JdawA=qXnP|m5eHp-vKHp!PH*>3(#b%Zp z2PZ{1wte$>H zbKPpBd9dcRiO3!~u+yP^7xB)$Cf<$or*g+$dJi0I)xywN)AFPu!nkrn&Ctqy{pzyc zj??S&ZR(@s^z=#iWNktZr^ePqNtHg0k&&sD)z6|LXyWm8o(vUi>}V@^py5Z>v-!K? zs%TS5xnb7>_8ek&qVRRSb>cc5F0N2DJEFY|?}>+ljZm+hF0?JM-$ zXF_mIw+e#lL^N`K)GY~l#*uAuFK-+>>*qnuI zC&z(B22@r-`zwQ5K_+o34n-YHE!eGQg?fuB=eCj*^!`Qj@j=l;tR7I&6k2EBHpL>2 zG<`9^n(C|IsZnT%}}$_ouaKn4(`|a2_hD#{r*ixaNXm9K~0>M zXXHq*`0%O3e1Nh`mQ&jz0;f#m3%wR|O{Op=T01Cq*O^9w<0>Cw8^dv^WFWlqW=LV3 z8B5BUI#efK8~5H;V4$SjGLa`J-T#@WpxZFM*4z+dh(^a=VZP!Q(@%`6MEZ6X{wB*a z51PYKeU>!RTGF7$hpA>qQWuX3AFesQ$XmVKKr(qj`jr3@RSkYWwD9kya&m7fokL{h zPSCa*jmce0ZR?AQ81udArmFXLXyTL3sEh(rw6Zm}tFyN#MwTW*8_x{uIAiC=!Z5M$ z0`V-EKIvP_n%3ry8y03SsjY_k_f2os$_y!?Jb^XE)w9he+<~Q%!Z>l~qlgR`7|@)gGEx~nhFer*+O?g=SA^91TYfj#uYj&3_{#y-d8)XqqQY}Y zuM!xy$f2?uzYU9=^oK8MJVn2N8mIdkdU+3af%%;{ON}IZeZR&WTo=LctlS*pU3e!$ zA+^7FRf=97#f7dEzD5QY?%G0h$;3WvEf%8wK5x+)g$_yGs@dViOIrs`7w-XC24>^o8{p0urI}=k@=qTtdAv=;nSGOzbmQZrkt#; z7gf>p&q|himzLwseVU>{L9zu`AL|4yYe~d_UF?Kg%Ipwm(zKJSn|~ z^tm5x5Bo=XBOvgjY+Wopdg(5d%sa?l_`Z$JoHyw2V9V_$7sIP`)idRH4Ry}P6+hO~ zRtBuvB!|merGlaWI!j_ldm@ zu69$|+N+jpYwJaag_4KatBxJVWoes?!Uv4xHKfX2m%W13dZs~1+O2HZP9sz#mK9f< zq)6KFTQ;RZRr_qa??mI{uTScMoVxw|xSs;OJQ62*LL-FG;e{a}e6y7J9}n989}a zcmQynKil9p%hX?6PM{_be5NzBKvmjJx3t4ZCxFbkFE-skRmq#8i@)faysu&r(?y^w zrz_svwun}{R5)j_cyiXSg0Ao_j;4`^@8upR3D?U3l(E{?$a;$4)B8eHef!O{BBV{VUU_iQf8^+XLEmG;_BgYiFv+yn#u zlW5O}aWfNdpOdyc(!9Ec0@qC*@r_Oie)LJP7=or(XC=CLTXac}xmpL5MWId%8@scD zQ~}Elrm*N%YW#4%h7*HU|o38&HUdbm;WolvJyOC`-*VHQ^e^M^Y!h_?0*7e z-~J#h$;U6+_E|8;G*>ez@x2fNM1bXNDA>UPGq^rOW7jP6`QXBG{iKdF-dM#o&@l70 zj`?q{xX10;t9L^{3?-raeSTAKc#h{RGi`#hm8|p_ij6|f$mL=JwP#$Zg93Nm7Yl>A z31t~ms@@Op$2ZrxF#rUAs<-IQgIcOV#0FYHtzIACgx#u+mKMlSuzrvXv)u{slcfswarLT`QZ%@+E>Mlp zVviq^m+qL>;_*b5dpX|8O?ElKB;=vVIJSXy5ntbF*I}==NZ#t3Qag~peYHLIT*lNK z>_c*k)X5;EN*za3Nvk4N&WX;BPdl|oSTWK-G;d{Mb;%8I*#v#ka-D&s);et;m}~WF?A8>PFq>#YqMvOcc}d0JIPxjCEt7U z?KB}9ZNm6;+QM22q*s5?z>;2rhuW>=Rrll;ycSAMG0M7PRM(}ynYvxjy3{JU(Gu6E zM>F@4{oAq*r$95YyXm6)Z0BbS*V0elZtpf3C}MRYKb7W}yS2}5K&pOtHX{JaFf~B| zBoox+aZ+C4I&!?p%Yyr+!{nueC>SB;p>Pij;ubJVkPXVM_51ql-RkqbFox?w3IpO= zO8h&x7nUmJRA9$1oqYSeQ_YpN!n7mSb<|->%6-$`R&MjvTXc8VJeRE1W~QFd=UP>> zQyR@iVeNuB%K*S!FoTfCp!V-A0>sF{3D%Pun;_TOfDLo)k50}|tW_edH!?9uqOD^8 z@rS7uvm6NwLhAfi*m1ptd_>3lw-;tx*o{)!IR!_u#{nMJ*EZ04iyC6U+HFIbk&rSd zHOl4wEb3AB>-y>rEfig&ZBm+ZSn;jH-}OpxVQnsAdcn0PpfQ-*3S-f7zaofN-mDEE z!0kXP+Zqi?UwF{HKO+3IMnX(bcOmr`g-=JRgYJ9}fjSQcoz--{5Q*ySdDGx!NV?R0 zSeBq#S$P_k>p?a6bK3Mqrj#MEd46Pl&RlX(N?3Ln3MOzWJCZN~QO{2FA_cxK-pe`{ z4Ef&02UC4_Lms;)pik@R@K($Iwt92;r&SNAiYi@gw5J9s>z+kV4ff*Vn1bKm4zx_| z5;1qpN*-MxZ`tj8bhi_T`97@3KorwU#hizF9S}aQSj2fmRO01(yAOoeD3FifI#ewr zhsd)RNoxWToi{z>y+fKRk9cjiEfb5cW$}^&?>2`OuvjQ<1o5Yj=dc~d%(&rY8DwFY z739-)sPW(atw;ZFGVx{)^4(q>=Y6MVt-z9Sjz+-vB%h z-@FcXzb;Y}8|Z9l(uQL73fx^-90<4E!=#S;YTe0#?A7*GvE1Rger5$4$=o^?w!fy4!xw?!4N;KgLVsh`-ixQ7l&kUd{~wK2_v@!XCl_w>Q5 zl+sd1I$pw=SAef?8$@-@q9MgoRK$Jw$Lpr)U<2O`-6=TjVwAm18aK8O2>Me~YuCR) zuKA)cP|nX;%Icf z1S)Ha>Z~k;s^}|j(bFkBm6iCZ=R@Al2A0;2kCf_y6}W4W0JiANLcc}gpI@B24t{3b zZY=O$rU=Mk48?q4qdn6A!l|dDB;N3%B2OvV*ka zN-i#PFIm@IUwrdasrzw+&$T>*2dJPdfn}CsF$UI-I)4>hK+tTA8_8pxK1(WJJ2i^@ zW0@WV90*%PCKs0Fjn$Tj+CRH(OHyt>EG*2J9cZqQ*3NRo^dO4|v>J1GijeTuaJt?K zz$K?GDP6yes#C5npN|;io^y%pk=GF>#w{IK$yU4gO$<<0NRA-bHWf1hKFWQ9PGod_ z>-vS^Mlg(nnnK(gU_08rN-->fINCYTBjrq!l1OG%^{zlDuAD;^y;^PGrBiom7#^KZ zw23ihMn)^1jF48aDdQ$RWyp!$V|Ja1WE6@Os$ur=DE=urpsJ*moQ6}P*lfu9(D|Za z;TfRrQ?rqfNnKvdSj_i0wV$3meayf;%smbDA2n|7(NpJdGmWfriT<@K=7q4Ay0qk{ zq*zx$6D98wxScYMI%~s|>4l5f=N*p@@qn_C@g(kiDzgj+I(ff%JAPB3)Z(h>+toc! zIkrXv%txO;reRW%K=<~$*ZlIZkm`PU zk0^Nf?%$?+8HKWY5;3rJ(+q5HqsdXyD2MdLj+0pwjZ$b@K9K*?zf{qYzesU|V2jQR zOdODN^_Zi}a$VHqChb)5b%`xkaJC0nXz2ld#-DEFZ1GrAmSU19M&Tz1xL>a)QND>A znY!V2M&-fz^IH?bcY$~6xAl$wl+fShZ!k5a?SJKu?A^QVgRZ7Ox{*F=oQl^8>-be+!Fk_-PL)_)0?%UR=?7_t+;hncP`JT z9T`Qjx3H7+TgPWzo`df=vi}C{>Xe1&1J1
    lGqU;L*M##OI>RqXdQ9K8XSUjH$H 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 Zu*0@{pHM1l7+a?TypmOwDUmh{`VVQkBsTy6