سادسا: تصميم المشفر الجيبي “Sinusoidal Encoder”


0038

0039 0040 0041 0042 0043 0044 0045 0046 0047

سادسا: تصميم المشفر الجيبي “Sinusoidal Encoder

يعتمد مبدأ عمل المشفر الجيبي على إعطاء إشارتين على الخرج، إحداهما جيبية والأخرى تجيبية (أي مزاحة بزاوية قدرها 90 درجة) ويمكن قياس السرعة من تردد هاتين الإشارتين. كما أن الإزاحة بينهما تدل على جهة الدوران ومنه يمكن حساب الموضع أيضا.

تصميم المشفر الجيبي بالطريقة المباشرة:

يعتمد التصميم في هذه الطريقة على المعادلة:

حيث أن  و . وأيضا:

نصمم الدارة التالية، والتي تحاكي عمل محرك تيار مستمر مع حساس Sinusoidal Encoder على خرجه. كما أنه تم إضافة تشويش على خطوط الحساس لتقريب الحالة أكثر من الحياة العملية:

تتم برمجة المحرك كما يلي:

/*

 * DC-Servo Motor Modelling

 * Copyright (c) 2006 by University of Aleppo

 *  All Rights Reserved

 */

#define S_FUNCTION_NAME namzaje_five_c_with_sino

#include <stddef.h>

#include <stdlib.h>

#include <math.h>

#include “simstruc.h”

#ifdef MATLAB_MEX_FILE

#include “mex.h”

#endif

#define SAMPLE_TIME_ARG         ssGetArg(S,0)

#define Ra_ARG                  ssGetArg(S,1)

#define La_ARG                  ssGetArg(S,2)

#define J_ARG                   ssGetArg(S,3)

#define B_ARG                   ssGetArg(S,4)

#define Cepsi_ARG               ssGetArg(S,5)

#define NUMBER_OF_ARGS          (6)

#define NSAMPLE_TIMES           (1)

#define NUMBER_OF_INPUTS        (2)  //U

#define NUMBER_OF_OUTPUTS       (5) // x=[] state vector

/*variables */

float Ts, Ra, La, J, B, Cepsi;

float tsam, U_K, TL_K, ia_K, ia_K_1, W_K, W_K_1, Theta_K, Theta_K_1, xa_k, xb_k, xa_k_1, xb_k_1;

static void mdlInitializeSizes(SimStruct *S)

{

    if (ssGetNumArgs(S) != NUMBER_OF_ARGS) {

#ifdef MATLAB_MEX_FILE

    mexErrMsgTxt(“Wrong number of input arguments passed.\nThree arguments are expected\n”);

#endif

    }

    /* Set up size information */

    ssSetNumContStates(    S, 0);      /* number of continuous states */

    ssSetNumDiscStates(    S, 5);      /* number of discrete states */

    ssSetNumInputs(        S, NUMBER_OF_INPUTS);      /* number of inputs */

    ssSetNumOutputs(       S, NUMBER_OF_OUTPUTS);      /* number of outputs */

    ssSetDirectFeedThrough(S, 0);      /* direct feedthrough flag */

    ssSetNumSampleTimes(   S, NSAMPLE_TIMES);      /* number of sample times */

    ssSetNumInputArgs(     S, NUMBER_OF_ARGS);      /* number of input arguments */

    ssSetNumRWork(         S, 0);      /* number of real work vector elements */

    ssSetNumIWork(         S, 0);      /* NUMBER_OF_IWORKS);      /* number of integer work vector elements */

    ssSetNumPWork(         S, 0);      /* number of pointer work vector elements */

}

static void mdlInitializeSampleTimes(SimStruct *S)

{

    ssSetSampleTimeEvent(S, 0, mxGetPr(SAMPLE_TIME_ARG)[0]);

    ssSetOffsetTimeEvent(S, 0, 0.0);

}

static void mdlInitializeConditions(double *x0, SimStruct *S)

{

/*Sampling Time*/

    tsam  = mxGetPr(SAMPLE_TIME_ARG)[0];

    Ra    = mxGetPr(Ra_ARG)[0];

    La    = mxGetPr(La_ARG)[0];

    J     = mxGetPr(J_ARG)[0];

    B     = mxGetPr(B_ARG)[0];

    Cepsi = mxGetPr(Cepsi_ARG)[0];

/* States initialization*/

ia_K_1=0;

W_K_1=0;

Theta_K_1=0;

xa_k_1=0;

xb_k_1=1;

Ra=11.8;

La=0.2;

Cepsi=0.945;

B=0.0006;

J=0.009;

}

static void mdlOutputs(double *y, double *x, double *u, SimStruct *S, int tid)

{

    /*Vo*/

y[0]= ia_K;

y[1]= W_K;

y[2]= Theta_K;

y[3]= xa_k;

y[4]= xb_k;

}

static void mdlUpdate(double *x, double *u, SimStruct *S, int tid)

{

//Model Update

    U_K= u[0];

    TL_K= u[1];

    ia_K=(1-(Ra/La)*tsam)*ia_K_1 + (-(Cepsi/La)*tsam)*W_K_1 + (tsam/La)*U_K;

    W_K=((Cepsi/J)*tsam)*ia_K_1 + (1-(B/J)*tsam)*W_K_1 + (-tsam/J)*TL_K;

    Theta_K = (tsam)*W_K_1 + Theta_K_1;

    xa_k = sin(Theta_K_1);

    xb_k = cos(Theta_K_1);

 //update value

ia_K_1=ia_K;

W_K_1=W_K;

Theta_K_1=Theta_K;

xa_k_1=xa_k;

xb_k_1=xb_k;

if(Theta_K_1 >= 6.283185307179586)

{

    Theta_K_1 = Theta_K_1 – 6.283185307179586;

    Theta_K = Theta_K – 6.283185307179586;

}

else if (Theta_K_1 < 0)

{

    Theta_K_1 = Theta_K_1 + 6.283185307179586;

    Theta_K = Theta_K + 6.283185307179586;

}

/*

 * mdlDerivatives – compute the derivatives

 *

 * In this function, you compute the S-function block’s derivatives.

 * The derivatives are placed in the dx variable.

 */

}

static void mdlDerivatives(double *dx, double *x, double *u, SimStruct *S, int tid)

{

}

/*

 * mdlTerminate – called when the simulation is terminated.

 *

 * In this function, you should perform any actions that are necessary

 * at the termination of a simulation.  For example, if memory was allocated

 * in mdlInitializeConditions, this is the place to free it.

 */

static void mdlTerminate(SimStruct *S)

{

}

#ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */

#include “simulink.c”      /* MEX-file interface mechanism */

#else

#include “cg_sfun.h”       /* Code generation registration function */

#endif

ثم نضيف مرحلة على الخرج تحول خرج الحساس إلى سرعة وموضع حقيقيين، وذلك عن طريق الصندوق sino ذي البرمجة التالية:

/*

 * DC-Servo Motor Modelling

 * Copyright (c) 2006 by University of Aleppo

 *  All Rights Reserved

 */

#define S_FUNCTION_NAME sino

#include <stddef.h>

#include <stdlib.h>

#include <math.h>

#include “simstruc.h”

#ifdef MATLAB_MEX_FILE

#include “mex.h”

#endif

#define SAMPLE_TIME_ARG         ssGetArg(S,0)

#define NUMBER_OF_ARGS          (1)

#define NSAMPLE_TIMES           (1)

#define NUMBER_OF_INPUTS        (2)  //U

#define NUMBER_OF_OUTPUTS       (2) // x=[] state vector

/*variables */

float tsam, Xa_k, Xa_k_1, Xb_k, Xb_k_1, w_k, w_k_1, theta_k, theta_k_1;

static void mdlInitializeSizes(SimStruct *S)

{

    if (ssGetNumArgs(S) != NUMBER_OF_ARGS) {

#ifdef MATLAB_MEX_FILE

    mexErrMsgTxt(“Wrong number of input arguments passed.\nThree arguments are expected\n”);

#endif

    }

    /* Set up size information */

    ssSetNumContStates(    S, 0);      /* number of continuous states */

    ssSetNumDiscStates(    S, 5);      /* number of discrete states */

    ssSetNumInputs(        S, NUMBER_OF_INPUTS);      /* number of inputs */

    ssSetNumOutputs(       S, NUMBER_OF_OUTPUTS);      /* number of outputs */

    ssSetDirectFeedThrough(S, 0);      /* direct feedthrough flag */

    ssSetNumSampleTimes(   S, NSAMPLE_TIMES);      /* number of sample times */

    ssSetNumInputArgs(     S, NUMBER_OF_ARGS);      /* number of input arguments */

    ssSetNumRWork(         S, 0);      /* number of real work vector elements */

    ssSetNumIWork(         S, 0);      /* NUMBER_OF_IWORKS);      /* number of integer work vector elements */

    ssSetNumPWork(         S, 0);      /* number of pointer work vector elements */

}

static void mdlInitializeSampleTimes(SimStruct *S)

{

    ssSetSampleTimeEvent(S, 0, mxGetPr(SAMPLE_TIME_ARG)[0]);

    ssSetOffsetTimeEvent(S, 0, 0.0);

}

static void mdlInitializeConditions(double *x0, SimStruct *S)

{

/*Sampling Time*/

    tsam  = mxGetPr(SAMPLE_TIME_ARG)[0];

/* States initialization*/

w_k_1=0;

theta_k_1=0;

Xa_k_1=0;

Xb_k_1=0;

}

static void mdlOutputs(double *y, double *x, double *u, SimStruct *S, int tid)

{

    /*Vo*/

y[0]=w_k;

y[1]=theta_k;

}

static void mdlUpdate(double *x, double *u, SimStruct *S, int tid)

{

//Model Update

    Xa_k= u[0];

    Xb_k= u[1];

    w_k=1/tsam*(Xa_k*Xb_k_1-Xb_k*Xa_k_1);

    theta_k=(w_k_1*tsam)+theta_k_1;

if(theta_k_1 >= 6.283185307179586)

{

    theta_k_1 = theta_k_1 – 6.283185307179586;

    theta_k = theta_k – 6.283185307179586;

}

else if (theta_k_1 < 0)

{

    theta_k_1 = theta_k_1 + 6.283185307179586;

    theta_k = theta_k + 6.283185307179586;

}

 //update value

w_k_1=w_k;

theta_k_1=theta_k;

Xa_k_1=Xa_k;

Xb_k_1=Xb_k;

/*

 * mdlDerivatives – compute the derivatives

 *

 * In this function, you compute the S-function block’s derivatives.

 * The derivatives are placed in the dx variable.

 */

}

static void mdlDerivatives(double *dx, double *x, double *u, SimStruct *S, int tid)

{

}

/*

 * mdlTerminate – called when the simulation is terminated.

 *

 * In this function, you should perform any actions that are necessary

 * at the termination of a simulation.  For example, if memory was allocated

 * in mdlInitializeConditions, this is the place to free it.

 */

static void mdlTerminate(SimStruct *S)

{

}

#ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */

#include “simulink.c”      /* MEX-file interface mechanism */

#else

#include “cg_sfun.h”       /* Code generation registration function */

#endif

ويكون خرج الحساس ظاهرا على Scope2:

أما بعد استخدام فاك الشيفرة Sino فنحصل على إشارة سرعة مشوشة للغاية، ونضيف مرشح تمرير منخفض للتغلب على هذه المشكلة، ويظهر Scope1 مقارنة بين إشارة السرعة المشوشة والإشارة ذاتها بعد الترشيح، أما الخط الثالث فهو للموضع:

  • تصميم المشفر الجيبي بالطريقة غير المباشرة:

نعتمد في هذه الطريقة على العلاقة التالية:

نصمم لها متحكم PI بحيث يصبح الفرق بين الزاوية الحقيقية والمخمنة يساوي الصفر، ولذلك نصمم الدارة التالية:

حيث يقوم Scope3 بعرض السرعة الحقيقية (الخط الأزرق) والسرعة المخمنة (الخط القرمزي، نلاحظ أن فيه تشويش ملحوظ بسبب وجود تشويش على خطوط نقل قراءة الحساس من المحرك) كما يلي:

أما بالنسبة للموضع الحقيقي والمخمن فيكون ظاهرا على Scope6 بالشكل التالي:

Advertisements

اترك رد

إملأ الحقول أدناه بالمعلومات المناسبة أو إضغط على إحدى الأيقونات لتسجيل الدخول:

WordPress.com Logo

أنت تعلق بإستخدام حساب WordPress.com. تسجيل خروج   / تغيير )

صورة تويتر

أنت تعلق بإستخدام حساب Twitter. تسجيل خروج   / تغيير )

Facebook photo

أنت تعلق بإستخدام حساب Facebook. تسجيل خروج   / تغيير )

Google+ photo

أنت تعلق بإستخدام حساب Google+. تسجيل خروج   / تغيير )

Connecting to %s