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 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