Project

Tilt & Telescopic Steering Column - ADAS Feature

Aim: To create a Model for Tilt and Telescopic Steering Column Switch according to the requirement and generate a C-code for it.

Objective:

  • Modelling the requirement based on MBD Guidelines
  • Create a Simulink Data Dictionary
  • Configuring Parameters
  • Generating Model Advisor report
  • Code Generation using Embedded Coder

Introduction:

ADAS stands for Advanced Driver Assistance System. It is basically an electronic system that helps the driver driving or during parking operations. The safety features are designed to avoid collisions and accidents by offering technologies that alert the driver mistakes by implementing safeguards and taking control of the vehicle.

Some of ADAS Features are: Adaptive cruise control, Autonomous Emergency braking, Blind spot detection, Tilt and Telescopic Steering Forward / Rearward collision warning system, Intelligent parking assistance, cross-traffic alert, etc.

Tilt and Telescopic Steering Column:

This Adas feature is widely used in modern automobiles which helps to adjust the steering wheel before the driver starts driving. The driver can adjust according to his/her comfort level. This feature also gives enough space for the driver which helps in entry/exit from the vehicle. Modern vehicles use an electronic switch in order to adjust the steering column to move UP, DOWN, FRONT and BACK. This adjustment should not affect the driver from seeing the instrument panel, warning lights, gauges and the infotainment system. The driver should not use this feature while driving. It may lead to losing control over the steering and could lead to accidents/injuries.

The Tilt and Telescopic Switch is responsible for Tilt / Tele Switch Input & performs:

• Switch Contact Debouncing.

• Determine the state of 4 directional switch — tilt up, tilt down, telescopic forward & telescopic rearward.

• Transmission of CAN signals.

• Detection of wakeup input activation

• Diagnostic monitoring of the switch input.

Tilt and Telescopic Steering Column- Function Diagram:

Requirements:

Requirement-1:

  • VMin- Defines minimum voltage for a voltage range = 10V
  • VMax- Defines maximum voltage for a voltage range = 20V
  • VBatt- Current Battery Voltage value within minimum maximum range =10V — 20V

Requirement-2:

  • Switch Handler Wake Up Behaviour: The Tilt Telescopic Switch interface has to wake up if the Ignition Status is RUN available at the CAN bus. At Wake Up, all the button states shall be in <Not_Pressed> state.

Requirement-3:

Tilt — Tele Stuck Switch Detection: The Tilt — Tele stuck switch status shall be set as <STUCK>, when the physical switch has been set in that position (up / down / forward / rearward) for more than 120 ms. At this point, the logical state shall be set to <STUCK> and the CAN signal will report to NULL.
When the Tilt—Tele stuck status is <UNSTUCK>, the logical state goes to <UNSTUCK> after 100ms. At this point, the CAN signal value is set based on the corresponding state of the physical switch. The ideal debounce time is 50ms.

Requirement-4:
Switch Debounce: The sensing modules shall debounce the buttons before the Tilt / Telescopic Switch function transmits the signal status.

Model:

Debounce Logic:

Similarly, all the modelling is done for - Tilt UP, Tilt DOWN, Tele FORWARD and Tele REARWARD.

Simulink DATA DICTIONARY:

Model Advisor Report:

Few Standard checks were selected and the testing was performed.

Code Generation:

/*
 * File: tilt_tele_switch_model.c
 *
 * Code generated for Simulink model 'tilt_tele_switch_model'.
 *
 * Model version                  : 1.42
 * Simulink Coder version         : 9.3 (R2020a) 18-Nov-2019
 * C/C++ source code generated on : Mon Sep  6 11:01:52 2021
 *
 * Target selection: ert.tlc
 * Embedded hardware selection: Intel->x86-64 (Windows64)
 * Code generation objectives: Unspecified
 * Validation result: Not run
 */

#include "tilt_tele_switch_model.h"
#include "tilt_tele_switch_model_private.h"

/* Named constants for Chart: '<S6>/Tilt_Down_Debounce_Logic' */
#define tilt_tele_sw_IN_NO_ACTIVE_CHILD ((uint8_T)0U)
#define tilt_tele_switc_IN_Off_Debounce ((uint8_T)1U)
#define tilt_tele_switch_IN_Not_Pressed ((uint8_T)2U)
#define tilt_tele_switch_IN_On_Debounce ((uint8_T)2U)
#define tilt_tele_switch__IN_Stuck_Wait ((uint8_T)6U)
#define tilt_tele_switch_mo_IN_Debounce ((uint8_T)1U)
#define tilt_tele_switch_mod_IN_Pressed ((uint8_T)4U)
#define tilt_tele_switch_model_IN_Off  ((uint8_T)3U)
#define tilt_tele_switch_model_IN_Stuck ((uint8_T)5U)

/* Exported data definition */

/* Definition for custom storage class: Localizable */
static TELE_INPUT Tele_Forward_Switch_Status_Delay;/* '<S9>/Delay' */
static TELE_INPUT Tele_Rearward_Switch_Status_Delay;/* '<S10>/Delay' */
static TILT_INPUT Tilt_Down_Switch_Status_Delay;/* '<S11>/Delay' */
static TILT_INPUT Tilt_Up_Switch_Status_Delay;/* '<S12>/Delay' */

/* Block signals (default storage) */
B_tilt_tele_switch_model_T tilt_tele_switch_model_B;

/* Block states (default storage) */
DW_tilt_tele_switch_model_T tilt_tele_switch_model_DW;

/* Real-time model */
RT_MODEL_tilt_tele_switch_mod_T tilt_tele_switch_model_M_;
RT_MODEL_tilt_tele_switch_mod_T *const tilt_tele_switch_model_M =
  &tilt_tele_switch_model_M_;
static void rate_scheduler(void);

/*
 *   This function updates active task flag for each subrate.
 * The function is called at model base rate, hence the
 * generated code self-manages all its subrates.
 */
static void rate_scheduler(void)
{
  /* Compute which subrates run during the next base time step.  Subrates
   * are an integer multiple of the base rate counter.  Therefore, the subtask
   * counter is reset when it reaches its limit (zero means run).
   */
  (tilt_tele_switch_model_M->Timing.TaskCounters.TID[1])++;
  if ((tilt_tele_switch_model_M->Timing.TaskCounters.TID[1]) > 999) {/* Sample time: [0.01s, 0.0s] */
    tilt_tele_switch_model_M->Timing.TaskCounters.TID[1] = 0;
  }
}

/* Model step function */
void tilt_tele_switch_model_step(void)
{
  if (tilt_tele_switch_model_M->Timing.TaskCounters.TID[1] == 0) {
    /* Outputs for Enabled SubSystem: '<S2>/SwitchPos_Status_Determination' incorporates:
     *  EnablePort: '<S4>/Enable'
     */
    /* Logic: '<S5>/LogicalOperator' incorporates:
     *  Constant: '<S3>/Vmax'
     *  Constant: '<S3>/Vmin'
     *  Inport: '<Root>/Input_Voltage'
     *  Inport: '<Root>/Tilt_Tele_Config_Param'
     *  Logic: '<S3>/LogicalOperator'
     *  RelationalOperator: '<S3>/GreaterThan'
     *  RelationalOperator: '<S3>/GreaterThan1'
     */
    if (((Input_Voltage >= ((uint8_T)10U)) && (Input_Voltage <= ((uint8_T)20U)))
        && Tilt_Tele_Config_Param) {
      /* Chart: '<S6>/Tilt_Down_Debounce_Logic' incorporates:
       *  Constant: '<S6>/Constant'
       *  Constant: '<S6>/Constant1'
       *  Constant: '<S6>/Constant2'
       *  DataStoreRead: '<S6>/DataStoreRead'
       *  Inport: '<Root>/Tilt_Down_Input'
       */
      if (tilt_tele_switch_model_DW.temporalCounter_i1_f < MAX_uint32_T) {
        tilt_tele_switch_model_DW.temporalCounter_i1_f++;
      }

      if (tilt_tele_switch_model_DW.is_active_c1_tilt_tele_switch_m == 0U) {
        tilt_tele_switch_model_DW.is_active_c1_tilt_tele_switch_m = 1U;
        tilt_tele_switch_model_DW.is_c1_tilt_tele_switch_model =
          tilt_tele_switch_IN_Not_Pressed;
        tilt_tele_switch_model_B.Down_Switch_Output = false;
      } else {
        switch (tilt_tele_switch_model_DW.is_c1_tilt_tele_switch_model) {
         case tilt_tele_switch_mo_IN_Debounce:
          switch (tilt_tele_switch_model_DW.is_Debounce_f) {
           case tilt_tele_switc_IN_Off_Debounce:
            break;

           default:
            /* case IN_On_Debounce: */
            if (tilt_tele_switch_model_DW.temporalCounter_i1_f >= ((uint32_T)
                 (k_SwitchDebounceTime * 100))) {
              tilt_tele_switch_model_DW.is_Debounce_f =
                tilt_tele_sw_IN_NO_ACTIVE_CHILD;
              tilt_tele_switch_model_DW.is_c1_tilt_tele_switch_model =
                tilt_tele_switch_mod_IN_Pressed;
              tilt_tele_switch_model_DW.temporalCounter_i1_f = 0U;
              tilt_tele_switch_model_B.Down_Switch_Output = true;
            }
            break;
          }
          break;

         case tilt_tele_switch_IN_Not_Pressed:
          tilt_tele_switch_model_B.Down_Switch_Output = false;
          if ((!Tilt_Down_Stuck_Switch) && Tilt_Down_Input) {
            tilt_tele_switch_model_DW.is_c1_tilt_tele_switch_model =
              tilt_tele_switch_mo_IN_Debounce;
            tilt_tele_switch_model_DW.is_Debounce_f =
              tilt_tele_switch_IN_On_Debounce;
            tilt_tele_switch_model_DW.temporalCounter_i1_f = 0U;
          }
          break;

         case tilt_tele_switch_model_IN_Off:
          if (tilt_tele_switch_model_DW.temporalCounter_i1_f >= ((uint32_T)
               (k_SwitchReleaseTime * 100))) {
            tilt_tele_switch_model_DW.is_c1_tilt_tele_switch_model =
              tilt_tele_switch_IN_Not_Pressed;
            tilt_tele_switch_model_B.Down_Switch_Output = false;
          }
          break;

         case tilt_tele_switch_mod_IN_Pressed:
          tilt_tele_switch_model_B.Down_Switch_Output = true;
          if (tilt_tele_switch_model_DW.temporalCounter_i1_f >= ((uint32_T)
               ((k_SwitchStuckTime - k_SwitchDebounceTime) * 100))) {
            tilt_tele_switch_model_DW.is_c1_tilt_tele_switch_model =
              tilt_tele_switch__IN_Stuck_Wait;
          } else {
            tilt_tele_switch_model_DW.is_c1_tilt_tele_switch_model =
              tilt_tele_switch_mo_IN_Debounce;
            tilt_tele_switch_model_DW.is_Debounce_f =
              tilt_tele_switc_IN_Off_Debounce;
          }
          break;

         case tilt_tele_switch_model_IN_Stuck:
          tilt_tele_switch_model_B.Down_Switch_Output = false;
          tilt_tele_switch_model_B.Switch_Stuck_n = true;
          if (!Tilt_Down_Input) {
            tilt_tele_switch_model_DW.is_c1_tilt_tele_switch_model =
              tilt_tele_switch_model_IN_Off;
            tilt_tele_switch_model_DW.temporalCounter_i1_f = 0U;
          }
          break;

         default:
          /* case IN_Stuck_Wait: */
          if (Tilt_Down_Input) {
            tilt_tele_switch_model_DW.is_c1_tilt_tele_switch_model =
              tilt_tele_switch_model_IN_Stuck;
            tilt_tele_switch_model_B.Down_Switch_Output = false;
            tilt_tele_switch_model_B.Switch_Stuck_n = true;
          }
          break;
        }
      }

      /* End of Chart: '<S6>/Tilt_Down_Debounce_Logic' */

      /* DataStoreWrite: '<S6>/DataStoreWrite' */
      Tilt_Down_Stuck_Switch = tilt_tele_switch_model_B.Switch_Stuck_n;

Code Contd..

              tilt_tele_switch_model_IN_Stuck;
            tilt_tele_switch_model_B.Rearward_Switch_Output = false;
            tilt_tele_switch_model_B.Switch_Stuck_p = true;
          }
          break;
        }
      }

      /* End of Chart: '<S8>/Tele_Rearward_Debounce_Logic' */

      /* DataStoreWrite: '<S8>/DataStoreWrite' */
      Tele_Rearward_Stuck_Switch = tilt_tele_switch_model_B.Switch_Stuck_p;

      /* Chart: '<S13>/Tilt_Up_Debounce_Logic' incorporates:
       *  Constant: '<S13>/Constant'
       *  Constant: '<S13>/Constant1'
       *  Constant: '<S13>/Constant2'
       *  DataStoreRead: '<S13>/DataStoreRead'
       *  Inport: '<Root>/Tilt_Up_Input'
       */
      if (tilt_tele_switch_model_DW.temporalCounter_i1 < MAX_uint32_T) {
        tilt_tele_switch_model_DW.temporalCounter_i1++;
      }

      if (tilt_tele_switch_model_DW.is_active_c3_tilt_tele_switch_m == 0U) {
        tilt_tele_switch_model_DW.is_active_c3_tilt_tele_switch_m = 1U;
        tilt_tele_switch_model_DW.is_c3_tilt_tele_switch_model =
          tilt_tele_switch_IN_Not_Pressed;
        tilt_tele_switch_model_B.Up_Switch_Output = false;
      } else {
        switch (tilt_tele_switch_model_DW.is_c3_tilt_tele_switch_model) {
         case tilt_tele_switch_mo_IN_Debounce:
          switch (tilt_tele_switch_model_DW.is_Debounce) {
           case tilt_tele_switc_IN_Off_Debounce:
            break;

           default:
            /* case IN_On_Debounce: */
            if (tilt_tele_switch_model_DW.temporalCounter_i1 >= ((uint32_T)
                 (k_SwitchDebounceTime * 100))) {
              tilt_tele_switch_model_DW.is_Debounce =
                tilt_tele_sw_IN_NO_ACTIVE_CHILD;
              tilt_tele_switch_model_DW.is_c3_tilt_tele_switch_model =
                tilt_tele_switch_mod_IN_Pressed;
              tilt_tele_switch_model_DW.temporalCounter_i1 = 0U;
              tilt_tele_switch_model_B.Up_Switch_Output = true;
            }
            break;
          }
          break;

         case tilt_tele_switch_IN_Not_Pressed:
          tilt_tele_switch_model_B.Up_Switch_Output = false;
          if ((!Tilt_Up_Stuck_Switch) && Tilt_Up_Input) {
            tilt_tele_switch_model_DW.is_c3_tilt_tele_switch_model =
              tilt_tele_switch_mo_IN_Debounce;
            tilt_tele_switch_model_DW.is_Debounce =
              tilt_tele_switch_IN_On_Debounce;
            tilt_tele_switch_model_DW.temporalCounter_i1 = 0U;
          }
          break;

         case tilt_tele_switch_model_IN_Off:
          if (tilt_tele_switch_model_DW.temporalCounter_i1 >= ((uint32_T)
               (k_SwitchReleaseTime * 100))) {
            tilt_tele_switch_model_DW.is_c3_tilt_tele_switch_model =
              tilt_tele_switch_IN_Not_Pressed;
            tilt_tele_switch_model_B.Up_Switch_Output = false;
          }
          break;

         case tilt_tele_switch_mod_IN_Pressed:
          tilt_tele_switch_model_B.Up_Switch_Output = true;
          if (tilt_tele_switch_model_DW.temporalCounter_i1 >= ((uint32_T)
               ((k_SwitchStuckTime - k_SwitchDebounceTime) * 100))) {
            tilt_tele_switch_model_DW.is_c3_tilt_tele_switch_model =
              tilt_tele_switch__IN_Stuck_Wait;
          } else {
            tilt_tele_switch_model_DW.is_c3_tilt_tele_switch_model =
              tilt_tele_switch_mo_IN_Debounce;
            tilt_tele_switch_model_DW.is_Debounce =
              tilt_tele_switc_IN_Off_Debounce;
          }
          break;

         case tilt_tele_switch_model_IN_Stuck:
          tilt_tele_switch_model_B.Up_Switch_Output = false;
          tilt_tele_switch_model_B.Switch_Stuck = true;
          if (!Tilt_Up_Input) {
            tilt_tele_switch_model_DW.is_c3_tilt_tele_switch_model =
              tilt_tele_switch_model_IN_Off;
            tilt_tele_switch_model_DW.temporalCounter_i1 = 0U;
          }
          break;

         default:
          /* case IN_Stuck_Wait: */
          if (Tilt_Up_Input) {
            tilt_tele_switch_model_DW.is_c3_tilt_tele_switch_model =
              tilt_tele_switch_model_IN_Stuck;
            tilt_tele_switch_model_B.Up_Switch_Output = false;
            tilt_tele_switch_model_B.Switch_Stuck = true;
          }
          break;
        }
      }

      /* End of Chart: '<S13>/Tilt_Up_Debounce_Logic' */

      /* DataStoreWrite: '<S13>/DataStoreWrite' */
      Tilt_Up_Stuck_Switch = tilt_tele_switch_model_B.Switch_Stuck;

      /* Switch: '<S9>/Switch' incorporates:
       *  Constant: '<S17>/Constant'
       *  Constant: '<S9>/Off'
       *  Delay: '<S10>/Delay'
       *  Delay: '<S11>/Delay'
       *  Delay: '<S12>/Delay'
       *  Delay: '<S9>/Delay'
       *  RelationalOperator: '<S17>/Compare'
       *  Sum: '<S4>/Add'
       *  Switch: '<S10>/Switch'
       *  Switch: '<S11>/Switch'
       *  Switch: '<S12>/Switch'
       *  Switch: '<S9>/Switch1'
       */
      if (((int32_T)(((((uint32_T)tilt_tele_switch_model_B.Up_Switch_Output) +
                       tilt_tele_switch_model_B.Down_Switch_Output) +
                      tilt_tele_switch_model_B.Forward_Switch_Output) +
                     tilt_tele_switch_model_B.Rearward_Switch_Output)) >
          ((uint8_T)1U)) {
        Tele_Forward_Switch_Status = Tele_Forward_Switch_Status_Delay;
        Tele_Rearward_Switch_Status = Tele_Rearward_Switch_Status_Delay;
        Tilt_Down_Switch_Status = Tilt_Down_Switch_Status_Delay;
        Tilt_Up_Switch_Status = Tilt_Up_Switch_Status_Delay;
      } else {
        if (tilt_tele_switch_model_B.Forward_Switch_Output) {
          /* Switch: '<S9>/Switch1' incorporates:
           *  Constant: '<S9>/Forward'
           */
          Tele_Forward_Switch_Status = TELE_Forward;
        } else {
          Tele_Forward_Switch_Status = TELE_Off;
        }

        /* Switch: '<S10>/Switch1' incorporates:
         *  Constant: '<S10>/Off'
         *  Constant: '<S10>/Rearward'
         *  Constant: '<S9>/Off'
         *  Switch: '<S9>/Switch1'
         */
        if (tilt_tele_switch_model_B.Rearward_Switch_Output) {
          Tele_Rearward_Switch_Status = TELE_Rearward;
        } else {
          Tele_Rearward_Switch_Status = TELE_Off;
        }

        /* End of Switch: '<S10>/Switch1' */

        /* Switch: '<S11>/Switch1' incorporates:
         *  Constant: '<S11>/Down'
         *  Constant: '<S11>/Off'
         */
        if (tilt_tele_switch_model_B.Down_Switch_Output) {
          Tilt_Down_Switch_Status = TILT_Down;
        } else {
          Tilt_Down_Switch_Status = TILT_Off;
        }

        /* End of Switch: '<S11>/Switch1' */

        /* Switch: '<S12>/Switch1' incorporates:
         *  Constant: '<S12>/Off'
         *  Constant: '<S12>/Up'
         */
        if (tilt_tele_switch_model_B.Up_Switch_Output) {
          Tilt_Up_Switch_Status = TILT_Up;
        } else {
          Tilt_Up_Switch_Status = TILT_Off;
        }

        /* End of Switch: '<S12>/Switch1' */
      }

      /* End of Switch: '<S9>/Switch' */

      /* Update for Delay: '<S9>/Delay' */
      Tele_Forward_Switch_Status_Delay = Tele_Forward_Switch_Status;

      /* Update for Delay: '<S10>/Delay' */
      Tele_Rearward_Switch_Status_Delay = Tele_Rearward_Switch_Status;

      /* Update for Delay: '<S11>/Delay' */
      Tilt_Down_Switch_Status_Delay = Tilt_Down_Switch_Status;

      /* Update for Delay: '<S12>/Delay' */
      Tilt_Up_Switch_Status_Delay = Tilt_Up_Switch_Status;
    }

    /* End of Logic: '<S5>/LogicalOperator' */
    /* End of Outputs for SubSystem: '<S2>/SwitchPos_Status_Determination' */
  }

  rate_scheduler();
}
/* Model initialize function */
void tilt_tele_switch_model_initialize(void)
{
  /* Registration code */

  /* block I/O */

  /* custom signals */
  Tilt_Down_Switch_Status = TILT_Up;
  Tilt_Up_Switch_Status = TILT_Up;
  Tele_Forward_Switch_Status = TELE_Forward;
  Tele_Rearward_Switch_Status = TELE_Forward;

  /* states (dwork) */

  /* custom states */
  Tele_Forward_Switch_Status_Delay = TELE_Forward;
  Tele_Rearward_Switch_Status_Delay = TELE_Forward;
  Tilt_Down_Switch_Status_Delay = TILT_Up;
  Tilt_Up_Switch_Status_Delay = TILT_Up;

  /* SystemInitialize for Enabled SubSystem: '<S2>/SwitchPos_Status_Determination' */
  /* InitializeConditions for Delay: '<S9>/Delay' */
  Tele_Forward_Switch_Status_Delay = TELE_Off;

  /* InitializeConditions for Delay: '<S10>/Delay' */
  Tele_Rearward_Switch_Status_Delay = TELE_Off;

  /* InitializeConditions for Delay: '<S11>/Delay' */
  Tilt_Down_Switch_Status_Delay = TILT_Off;

  /* InitializeConditions for Delay: '<S12>/Delay' */
  Tilt_Up_Switch_Status_Delay = TILT_Off;

  /* SystemInitialize for Outport: '<S4>/Tilt_Up_Switch_Status' */
  Tilt_Up_Switch_Status = TILT_Up;

  /* SystemInitialize for Outport: '<S4>/Tilt_Down_Switch_Status' */
  Tilt_Down_Switch_Status = TILT_Up;

  /* SystemInitialize for Outport: '<S4>/Tele_Forward_Switch_Status' */
  Tele_Forward_Switch_Status = TELE_Forward;

  /* SystemInitialize for Outport: '<S4>/Tele_Rearward_Switch_Status' */
  Tele_Rearward_Switch_Status = TELE_Forward;

  /* End of SystemInitialize for SubSystem: '<S2>/SwitchPos_Status_Determination' */
}

/* Model terminate function */
void tilt_tele_switch_model_terminate(void)
{
  /* (no terminate code required) */
}

/*
 * File trailer for generated code.
 *
 * [EOF]
 */

Conclusion:

The Tilt & Telescopic Steering Column Model is Developed and SLDD is created according to requirements.The model can be tested for MIL and SIL by creating a test harness for the model using the functional test cases.The S-funcion can be created with the generated Code and can be implemented for vehicle level testing.

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.