Материал: Разработка системы управления механической системы в режиме мягкого реального времени

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

.        Модуль GotoY. Вызывается при нажатии на кнопку Goto_0Y. В обработчике этого события переменной vihod_0Y_cmd присваивается значение 1

.        Модуль Openfile. Открывает файл с командами и записывает его содержимое в переменную program, которая представляет собой указатель на строку.

.        Модуль Start.Разрешает задаче ProgControl начать выполнение команд оператора.

.        Модуль Stop.Останавливает выполнение команд оператора.

Теперь рассмотрим разработку второго - основного потока, который непосредственно выполняет задачи управления движением.

Разработка велась по методике /1/, согласно которой каждая задача, имеющая структуру состояний программируется как отдельная Cи-функция. Для обмена данными между задачами используются глобальные переменные. Если имеется необходимость настройки некоторой задачи, т.е выполнения каких либо действий, касающихся этой задачи до начала или после окончания ей работы, для этой задачи программируются функции инициализации и окончания работы. Все функции и данные, относящиеся к задаче, помещаются в c-файл. В соответствующем заголовочном h-файле объявляются функции и переменные, используемые в других частях программы. Спецификация модулей СРВ представлена в таблице 4.1. Листинги программного кода функций основного процесса приведены в приложении А.

Для того чтобы использовать меньше машинного времени в процессе выполнения движения, мы пришли к решению: рассчитать характеристики движения на этапе инициализации и занести их в определенный массив, тем самым в основном цикле для управления ШД мы будем обращаться к данному массиву.

Главная функция c-программы состоит из трёх секций:

1.      Секция инициализации, в которой вызываются функции инициализации тех задач, для которых они предусмотрены. Среди таких функций:

-   InOutTask_init() - инициализация портов ввода/вывода;

Так же в этом разделе происходит инициализация переменных, используемых в задачах;

Это функция рассчитывает характеристики движения по формулам (1.1),(1.2) на каждом шаге в процессе разгона и заносит их в массивы mainmass_x и mainmass_y. Они имеют следующую структуру:

uint64_t dt_ms - интервал времени между импульсами в мс;

uint64_t dt - интервал времени между импульсами в тактах процессора;

V - скорость.

Также здесь происходит инициализация глобальных переменных, если это необходимо.

2.      Основной цикл, в котором поочерёдно вызываются функции каждой задачи. Выход из цикла контролируется специальной переменной work.

3.      Секция завершения, в которой вызываются функции завершения:

-   InOutTask_close () - завершение работы портов ввода/вывода;

-       Save() - сохранение записей в файле log.dat;

Для тестирования программы создается файл log.dat, в котором записываются переходы каждой задачи из одного состояния в другое и сохраняются моменты времени этих переходов. Тем самым, использую данный файл, мы сможем проанализировать работу нашей программы, сможем определить, насколько приближенны реальные характеристики движения (интервалы времени, скорость, ускорения) к своим рассчитанным значениям.

Каждая функция задачи программируется по определённому шаблону /4/. Для задачи должны быть определены: набор уникальных имён состояний и уникальный идентификатор задачи. Для каждого состояния программируются три секции:

-             секция входа, в которой программируются действия, выполняемые при входе задачи в состояние;

-             секция действия, в котором программируется содержательная часть работы в данном состоянии;секция перехода, в которой проверяются условия и выполняются действия, связанные с переходом в следующее состояние.

6. Отладка ПО РВ

При запуске программы производится чтение из файла. Для проверки

правильности работы программы мы смотрим файл Log.dat. Переход состояний происходит согласно диспетчеру состояний.

Рисунок 6.1 - Программа в рабочем состоянии.

Заключение

В ходе выполнения данной работы были рассмотрены и применены при разработке ПО РВ основные принципы и метода проектирования систем реального времени.

На этапе технического проектирования были выделены и описаны задачи будущей СРВ в соответствии с конструктивными и функциональными особенностями объекта управления, после чего была построена диаграмма задач, в которой размещены все задачи проектируемой СРВ и указаны каналы связи между ними. Для каждой задачи была подробно рассмотрена специфика процесса управления, на основании которой была построена структура задач. Для задач, не имеющих структуру состояний, были изложены алгоритмы в текстовой форме.

В результате проделанной работы были сформулированы конкретные требования к каждой из задач для будущего проектирования с привязкой к вычислительной технологии и разработки ПО РВ.

Список использованных источников

1.      Управляющие программы для механических систем: объектно-ориентированное проектирование систем реального времени/ Д.М. Ослэндер, Дж.Р. Риджли, Дж.Д. Ринггенберг; Пер. с англ. - М.: БИНОМ. Лаборатория знаний, 2004.

2.      Операционная система реального времени QNX от теории к практике / С. Зыль. - СПб.: БХВ-Санкт-Петербург, 2004 г.

.        Введение в QNX/Neutrino-2. Руководство для разработчиков приложений реального времени. / Р. Кёртен, К. Херборт; Пер. с англ. - СПб.: Петрополис. Санкт-Петербург, 2001 г.

Приложения

А.1 Листинг кода задачи Main_cicle.

void* work_thread( void* arg )

{i;timed;vardt;*fp;=1;_x[0].V=0;_x[0].St=0;_x[0].dt=0;_x[0].dt_ms=0;_y[0].V=0;_y[0].St=0;_y[0].dt=0;_y[0].dt_ms=0;= fopen( "log1.dat", "w" );(mainmass_x[i-1].V<=Vmax_x) {

//while (i<4) {=(-mainmass_x[i-1].V+sqrt(mainmass_x[i-1].V*mainmass_x[i-1].V+2*a_x*Ssh_x))/a_x;_x[i].dt_ms=round(vardt*1000);=vardt*1000;_x[i].dt=SYSPAGE_ENTRY(qtime)->cycles_per_sec *vardt ;_x[i].V=mainmass_x[i-1].V+a_x*vardt;_x[i].St=i*Ssh_x;( fp,"dt:%d \n",mainmass_x[i].dt_ms);( fp," V_x:%f \n",mainmass_x[i].V);=i+1;

}_step_x=i-1;( fp," a_x:%f \n",a_x);( fp," Vmaxindexstep:%d \n",Vm_step_x);( fp," Vmax_x:%f \n",Vmax_x);( fp," Ssh_x:%f \n",Ssh_x);( fp," Vmaxx_x:%f \n",mainmass_x[Vm_step_x].V);( fp );=1;= fopen( "log2.dat", "w" );(mainmass_y[i-1].V<=Vmax_y) {

//while (i<4) {=(-mainmass_y[i-1].V+sqrt(mainmass_y[i-1].V*mainmass_y[i-1].V+2*a_y*Ssh_y))/a_y;_y[i].dt_ms=round(vardt*1000);=vardt*1000;_y[i].dt=SYSPAGE_ENTRY(qtime)->cycles_per_sec *vardt ;_y[i].V=mainmass_y[i-1].V+a_y*vardt;_y[i].St=i*Ssh_y;( fp,"dt:%d \n",mainmass_y[i].dt_ms);( fp," V_y:%f \n",mainmass_y[i].V);=i+1;

}_step_y=i-1;( fp," a_y:%f \n",a_y);( fp," Vmaxindexstep:%d \n",Vm_step_y);( fp," Vmax_y:%f \n",Vmax_y);( fp," Ssh_y:%f \n",Ssh_y);( fp," Vmaxx_y:%f \n",mainmass_y[Vm_step_y].V);( fp );

// if ( fp != NULL )

// for ( i=0; i <= Vm_step_x; i++ )_init(1000000);

// инициализация задач( InOutTask_init() != 0 ) { return -1; };(sled_x_init() != 0 ) {return -1;}(goto_0X_init() != 0 ) {return -1;}= 1;(work)

{();// Задача ввода входных данных_x();

// task3();_0X();_y();_0Y();();// Задача вывода выходных данных

};(0);();

//деинициализация задач(InOutTask_close() !=0) {return -1;};

// сохраним протокол работы системы();

return( 0 );

}_cicle( PtWidget_t *widget, ApInfo_t *apinfo, PtCallbackInfo_t *cbinfo )

{_attr_t attr;

/* eliminate 'unreferenced' warnings */= widget, apinfo = apinfo, cbinfo = cbinfo;_attr_init( &attr );_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );_create( NULL, &attr, &work_thread, NULL );_mutex_init( &mutex ,NULL);( Pt_CONTINUE );

}

А.2 Листинг кода задачи Sled_X

sled_x (void)

{FILE *fp1;short int temp;

// переменные состоянийint STATE = INITSTATE; // текущее состояние задачи

static int NEXTSTATE = STOP_Sx; // следующее состояние задачи (если задача не изменила своё состояние, то =-1 Если на данном просмотре она не меняет своего состояния, то NextStatee=-1*/;int RUNENTRY;// признак выполнения секции входа для данного состоянияint phase=1;

//интервалыuint64_t dt;// временной интервал между шагами в тактах

// Переменныеuint64_t TendStep;// время окончания шага в тактахuint64_t TendT;// время окончания срабатывания тормоза в тактах

static int sost; //int64_t dx;

if (NEXTSTATE != -1) // задача изменила своё состояние

{(TASKID,STATE,NEXTSTATE);// зарегистрируем это событие

STATE = NEXTSTATE;= -1;= 1;

}RUNENTRY = 0;(STATE)

{STOP_Sx:

// секция входа(RUNENTRY) {

};((vihod_0X==1) && (vihod_0Y==1)) {

// //printf("xt\n%d\n",Xt);

// //printf("xc\n%d\n",Xc);=Xc-Xt;(dx!=0) {_x=0;= BRAKE_Sx;=STOP_Sx;

}

};BRAKE_Sx:

// секция входа(RUNENTRY) {(sost==STOP_Sx) {(num_Tx);= getoutbuf() & phases_mask_x;( temp | phases_signals_x[0]);

} else {(num_Tx);= getoutbuf() & phases_mask_x;( temp | 0);_x=0;

}=ClockCycles()+Ttormoz;

}(ClockCycles() >=TendT) {(sost==STOP_Sx) {(dx==1) {NEXTSTATE=STEP_Sx;} else {=ACCEL_Sx;}

} else {NEXTSTATE =STOP_Sx;}

};ACCEL_Sx:

// секция входа(RUNENTRY) {

};=(Xc-Xt);(((dx>0) && (Vt_x<0)) || ((dx<0) && (Vt_x>0))) {NEXTSTATE=DEACCEL_Sx; }(abs(dx)<=indexstep_x) {NEXTSTATE=DEACCEL_Sx; }{_x=indexstep_x+1;=mainmass_x[indexstep_x].dt; //v taktah( dx>0 ) { if ( ++phase > 4) { phase = 1; }; };( dx<0 ) { if ( --phase < 1 ) { phase = 4; }; };= getoutbuf() & phases_mask_x;( temp | phases_signals_x[ phase -1]);((indexstep_x==Vm_step_x)&&((abs(dx)-1)>indexstep_x)) {sost=CONST_Sx;}((abs(dx)-1)<=indexstep_x) {sost=DEACCEL_Sx;}((indexstep_x<Vm_step_x)&&((abs(dx)-1)>indexstep_x)) {sost=ACCEL_Sx;}=WAIT_Sx;

};WAIT_Sx:

// секция входа(RUNENTRY) {=ClockCycles()+dt;

}(ClockCycles() >=TendStep ) {=sost;(dx>0) {Xt=Xt+1; Vt_x=mainmass_x[indexstep_x].V;}{Xt=Xt-1; Vt_x=-mainmass_x[indexstep_x].V;}

// if (Yt==300) { task_x=1;}

//printf("Vt_y\n%f\n",Vt_y);

//printf("x\n%d\n",Yt);

};DEACCEL_Sx:

// секция входа(RUNENTRY) {

//printf("DEACCEL\n%d\n");

};=(Xc-Xt);((((dx>0)&&(Vt_x>0)) || ((dx<0)&&(Vt_x<0)))&& (abs(dx)>indexstep_x)) {(indexstep_x<Vm_step_x) {NEXTSTATE=ACCEL_Sx; } else {NEXTSTATE=CONST_Sx;} }{_x=indexstep_x-1;=mainmass_x[indexstep_x].dt; //v taktah( dx>0 ) { if ( ++phase > 4) { phase = 1; }; };( dx<0 ) { if ( --phase < 1 ) { phase = 4; }; };= getoutbuf() & phases_mask_x;( temp | phases_signals_x[ phase -1]);(indexstep_x==0) {sost=BRAKE_Sx;} else {sost=DEACCEL_Sx;}=WAIT_Sx;

//printf("dt_ms\n%d\n",mainmass_y[indexstep_y].dt_ms);

};CONST_Sx:

// секция входа(RUNENTRY) {

//printf("CONST\n%d\n");

};=(Xc-Xt);((((dx>0)&&(Vt_x<0)) || ((dx<0)&&(Vt_x>0)))|| (abs(dx)<=indexstep_x)) {NEXTSTATE=DEACCEL_Sx; }{((abs(dx)-1)<=indexstep_x) {sost=DEACCEL_Sx;} else {sost=CONST_Sx;}( dx>0 ) { if ( ++phase > 4) { phase = 1; }; };( dx<0 ) { if ( --phase < 1 ) { phase = 4; }; };= getoutbuf() & phases_mask_x;( temp | phases_signals_x[ phase -1]);=WAIT_Sx;

};STEP_Sx:

// секция входа(RUNENTRY) {

//printf("CONST\n%d\n");

};

//dx=(Xc-Xt);

// if ((((dx>0)&&(Vt_x<0)) || ((dx<0)&&(Vt_x>0)))|| (abs(dx)<=indexstep_x)) {NEXTSTATE=DEACCEL_Sx; }

// else {

// if ((abs(dx)-1)<=indexstep_x) {sost=DEACCEL_Sx;} else {sost=CONST_Sx;}_x=1;=mainmass_x[indexstep_x].dt; //v taktah( dx>0 ) { if ( ++phase > 4) { phase = 1; }; };( dx<0 ) { if ( --phase < 1 ) { phase = 4; }; };= getoutbuf() & phases_mask_x;( temp | phases_signals_x[ phase -1]);=BRAKE_Sx;=WAIT_Sx;

//};: work =0;

} // end swith

};

//_x_init(void)

{= SYSPAGE_ENTRY(qtime)->cycles_per_sec / 1000 * Ttormoz_ms;

//printf("sled_x_init\n"); 0;

};

А.3 Листинг кода задачи Sled_Y

int sled_y (void)

{short int temp;

// переменные состоянийint STATE = INITSTATE; // текущее состояние задачиint NEXTSTATE = STOP_S;// следующее состояние задачи (если задача не изменила своё состояние, то =-1 Если на данном просмотре она не меняет своего состояния, то NextStatee=-1*/;int RUNENTRY;// признак выполнения секции входа для данного состоянияint phase=1;

//интервалыuint64_t dt;// временной интервал между шагами в тактах

// Переменныеuint64_t TendStep;// время окончания шага в тактахuint64_t TendT;// время окончания срабатывания тормоза в тактах

static int sost; //int BSM_x;int64_t dy;(NEXTSTATE != -1) // задача изменила своё состояние

{(TASKID,STATE,NEXTSTATE);// зарегистрируем это событие

STATE = NEXTSTATE;= -1;= 1;

}RUNENTRY = 0;(STATE)

{STOP_S:

// секция входа(RUNENTRY) {

//printf("STOP_y\n%d\n");

//printf("STOP_yt\n%d\n",Yt);

};((vihod_0X==1) && (vihod_0Y==1)) {

// //printf("xt\n%d\n",Xt);

// //printf("xc\n%d\n",Xc);=Yc-Yt;(dy!=0) {_y=0;= BRAKE_S;=STOP_S;

}

};BRAKE_S:

// секция входа(RUNENTRY) {

//printf("BRAKE\n%d\n");(sost==STOP_S) {(num_Ty);= getoutbuf() & phases_mask_y;( temp | phases_signals_y[0]);

} else {(num_Ty);= getoutbuf() & phases_mask_y;( temp | 0);_y=0;

}=ClockCycles()+Ttormoz;

//printf("x\n%d\n",Yt);

}(ClockCycles() >=TendT) {

//printf("x\n%d\n",Yt);(sost==STOP_S) {(dy==1) {NEXTSTATE=STEP_S;} else {NEXTSTATE =ACCEL_S;}

} else {NEXTSTATE =STOP_S;}

};ACCEL_S:

// секция входа(RUNENTRY) {

//printf("ACCEL\n%d\n");

};

// //printf("Vt_x\n%f\n",Vt_x);

// //printf("dx\n%f\n",dx);

// //printf("st\n%f\n",St);

// //printf("xt\n%llu\n",Xt);

// //printf("xc\n%llu\n",Xc);=(Yc-Yt);(((dy>0) && (Vt_y<0)) || ((dy<0) && (Vt_y>0))) {NEXTSTATE=DEACCEL_S; }(abs(dy)<=indexstep_y) {NEXTSTATE=DEACCEL_S; }{_y=indexstep_y+1;=mainmass_y[indexstep_y].dt; //v taktah( dy>0 ) { if ( ++phase > 4) { phase = 1; }; };( dy<0 ) { if ( --phase < 1 ) { phase = 4; }; };= getoutbuf() & phases_mask_y;( temp | phases_signals_y[ phase -1]);((indexstep_y==Vm_step_y)&&((abs(dy)-1)>indexstep_y)) {sost=CONST_S;}((abs(dy)-1)<=indexstep_y) {sost=DEACCEL_S;}((indexstep_y<Vm_step_y)&&((abs(dy)-1)>indexstep_y)) {sost=ACCEL_S;}=WAIT_S;

//printf("dt\n%d\n",dt);

//printf("dt_ms\n%d\n",mainmass_y[indexstep_y].dt_ms);

};WAIT_S:

// секция входа(RUNENTRY) {

//printf("WAIT\n%d\n");

//printf("dt\n%d\n",dt);=ClockCycles()+dt;

// //printf("clock\n%d\n",ClockCycles());

// //printf("TendStep\n%d\n",TendStep);

}(ClockCycles() >=TendStep ) {=sost;(dy>0) {Yt=Yt+1; Vt_y=mainmass_y[indexstep_y].V;}{Yt=Yt-1; Vt_y=-mainmass_y[indexstep_y].V;}

// if (Yt==300) { task_x=1;}

//printf("Vt_y\n%f\n",Vt_y);

//printf("x\n%d\n",Yt);

};DEACCEL_S:

// секция входа(RUNENTRY) {

//printf("DEACCEL\n%d\n");

};=(Yc-Yt);((((dy>0)&&(Vt_y>0)) || ((dy<0)&&(Vt_y<0)))&& (abs(dy)>indexstep_y)) {(indexstep_y<Vm_step_y) {NEXTSTATE=ACCEL_S; } else {NEXTSTATE=CONST_S;} }{_y=indexstep_y-1;=mainmass_y[indexstep_y].dt; //v taktah( dy>0 ) { if ( ++phase > 4) { phase = 1; }; };( dy<0 ) { if ( --phase < 1 ) { phase = 4; }; };= getoutbuf() & phases_mask_y;( temp | phases_signals_y[ phase -1]);(indexstep_y==0) {sost=BRAKE_S;} else {sost=DEACCEL_S;}=WAIT_S;

//printf("dt_ms\n%d\n",mainmass_y[indexstep_y].dt_ms);

};CONST_S:

// секция входа(RUNENTRY) {

//printf("CONST\n%d\n");

};=(Yc-Yt);((((dy>0)&&(Vt_y<0)) || ((dy<0)&&(Vt_y>0)))|| (abs(dy)<=indexstep_y)) {NEXTSTATE=DEACCEL_S; }{((abs(dy)-1)<=indexstep_y) {sost=DEACCEL_S;} else {sost=CONST_S;}( dy>0 ) { if ( ++phase > 4) { phase = 1; }; };( dy<0 ) { if ( --phase < 1 ) { phase = 4; }; };= getoutbuf() & phases_mask_y;( temp | phases_signals_y[ phase -1]);=WAIT_S;

};STEP_S:

// секция входа(RUNENTRY) {

//printf("CONST\n%d\n");

};

//dx=(Xc-Xt);

// if ((((dx>0)&&(Vt_x<0)) || ((dx<0)&&(Vt_x>0)))|| (abs(dx)<=indexstep_x)) {NEXTSTATE=DEACCEL_Sx; }

// else {

// if ((abs(dx)-1)<=indexstep_x) {sost=DEACCEL_Sx;} else {sost=CONST_Sx;}_y=1;=mainmass_y[indexstep_y].dt; //v taktah( dy>0 ) { if ( ++phase > 4) { phase = 1; }; };( dy<0 ) { if ( --phase < 1 ) { phase = 4; }; };= getoutbuf() & phases_mask_y;( temp | phases_signals_y[ phase -1]);=BRAKE_S;=WAIT_S;

//};: work =0;

} // end swith

};

//_y_init(void)

{= SYSPAGE_ENTRY(qtime)->cycles_per_sec / 1000 * Ttormoz_ms;

//printf("sled_y_init\n");

return 0;

};