Транспортный авиационный робот

Материал из roboforum.ru Wiki
Версия от 09:19, 22 сентября 2009; Setar (обсуждение | вклад) (ЭЛЕКТРИЧЕСКИЕ СХЕМЫ И СПЕЦИФИКАЦИИ)
Перейти к: навигация, поиск


Источники: [1] Обсуждение на форуме

ЭЛЕКТРИЧЕСКИЕ СХЕМЫ И СПЕЦИФИКАЦИИ

Для просмотра схем и чертежей используйте sPlan v.5

СХЕМА ЭЛЕКТРИЧЕСКАЯ СТРУКТУРНАЯ

Смотрите в файле "Э1.spl" .

СХЕМА ЭЛЕКТРИЧЕСКАЯ ФУНКЦИОНАЛЬНАЯ

Смотрите в файле "Э2.spl" .

СХЕМЫ ЭЛЕКТРИЧЕСКИЕ ПРИНЦИПИАЛЬНЫЕ

Нумерация в позиционных обозначениях ЭРЭ и прочих компонент, указанных на принципиальных схемах всех узлов и блоков - сквозная.

ОПИСАНИЕ ВНЕШНИХ СИГНАЛОВ МОДУЛЯ УЭВМ

"ПРОШИВКА_7..9" - для прошивки программ ПЗУ однокристальных микроконтроллеров "TAHO[0..2]" - 3-битовый паралл. код значения средн. угл. скор. вращ. вала мотора "TEMPERATURE" - аналоговое значение температуры мотора "RADIO_RMT_CTRL[0..2]" - 3-битовый паралл. код команд радиоуправления "SELF_CLK" - тактовый сигнал на регистр сдвига модуля драйверов "SELF_CLK1" - тактовый сигнал на регистр сдвига модуля драйверов "SELF_DATES" - бит данных для регистра сдвига модуля драйверов

          (приставка "SELF" - бортовые сервоустройства)

"TRG_CLK" - тактовый сигнал на регистр сдвига модуля драйверов "TRG_CLK1" - тактовый сигнал на регистр сдвига модуля драйверов "TRG_DATES" - бит данных для регистра сдвига модуля драйверов

          (приставка "TRG" - целевые сервоустройства)

"ПУСК1" , "ПУСК2" - биты команд общего пуска всей машины "SHASSY" - бит от шасси, для определения момента отрыва от ВПП и касания ВПП "SENS[0..7]" - байт паралл. кода от сенсоров "GPS" - от GPS-модуля "SET_GPS_RS" - на GPS-модуль "GND" - "Общий" для всей электросети "GND_CUT" - "Общий" для логики модуля УЭВМ, части периферии(тахометр,термометр,

          сенсоры,GPS-модуль,радиоприемник_СДУ), и при этом гальванически
          не связанный с "Общим" всей остальной электросети

"VCC" - (+5) [В] питания логики(TTL) модуля драйверов и всей остальной э/сети "VCC_CUT" - (+5) [В] питания логики(TTL, СБИС ОМК) модуля УЭВМ, части периферии

          (тахометр,термометр,сенсоры,GPS-модуль,радиоприемник_СДУ), и при 
          этом гальванически не связанный с "VCC" всей остальной электросети

"START" - бит. команда на систему электропуска и электрозажигания мотоагрегата

КОМАНДЫ РАДИОУПРАВЛЕНИЯ

"РУЛЬ_ВЛЕВО" "РУЛЬ_ВПРАВО" "РУЛЬ_ВНИЗ" "ГАЗ_САМЫЙ_МАЛЫЙ" "ГАЗ_БОЛЬШОЙ" "ПУСК" "ТОРМОЗ" "АВТОМАТИКА" - это команда, устанавлив-я по умолч-ю, при ней нет радиоуправления

ОПИСАНИЕ ВНУТРЕНИХ СИГНАЛОВ МОДУЛЯ УЭВМ

"INTERRUPT_1,2" - прерывание от второго ОМК на первый ОМК "D_TRANS[0..15]" - 16-битовый паралл. код магистрали обмена данных "ОМК#1 <-> ОМК#2" "FLAG_MCU_1[0..2]" - 3-битовый флаг состояния ОМК#1 "FLAG_MCU_2[0..2]" - 3-битовый флаг состояния ОМК#2 "SENSOR_CLK" - тактовый сигнал на регистр сдвига буфера бит от сенсоров "SENSOR_DATES" - бит данных от регистра сдвига буфера бит от сенсоров(помимо сенсоров

          технологических устройств, здесь также два бита команд общего запуска,
          и бит от шасси)

"SENSOR_LD" - управление режимом работы регистра сдвига(сдвиг или загрузка) и

          загрузки бит от сенсоров

ОПИСАНИЕ СИГНАЛОВ МОДУЛЯ ДРАЙВЕРОВ

"ВЛЕВО" - фаза на электромагнит соотв. руля

       (для поворота по часовой стрелке(вид сверху) руля курса)

"ВПРАВО" - фаза на э/магнит соотв. руля

       (для поворота против часовой стрелке(вид сверху) руля курса)

"ВНИЗ" - фаза на э/магнит соотв. руля

       (для поворота по часовой стрелке(вид слева по ходу) руля тангажа)

"ЕЛЕ-ЕЛЕ" - фаза на э/магнит устанавливающего дроссель газа в положение "ГАЗ_САМЫЙ_МАЛЫЙ" "МАЛЫЙ" - фаза на э/магнит устанав-го дроссель газа в полож. "ГАЗ_МАЛЫЙ" "СРЕДНИЙ" - фаза на э/магнит устанав-го дроссель газа в полож. "ГАЗ_СРЕДНИЙ" "БОЛЬШОЙ" - фаза на э/магнит устанав-го дроссель газа в полож. "ГАЗ_БОЛЬШОЙ" "ЗАПУСК" - (+12) [В] на систему электропуска и электрозажигания мотоагрегата "ОСТАНОВ" - фаза на э/магнит тормоза колес шасси "TRG_SRV[0..7]" - (+12) [В] на технол.(целевые) сервоустр-ва "TRG_SRV_PH[0..7]" - фаза на каждое отдельное технол.(целевое) сервоустр-во "PHASE" - фаза

ОПИСАНИЕ СИГНАЛОВ БОРТОВЫХ СЕНСОРОВ

"ПУСК1" , "ПУСК2" - биты команд общего пуска всей машины "SHASSY" - бит от шасси, для определения момента отрыва от ВПП и касания ВПП

ОПИСАНИЕ ЭЛЕКТРОПИТАНИЯ

Первичных источников электропитания всего два. На функциональной электросхеме они изображены в виде блоков, первый из них - "Аккумуляторная ба- тарея", второй - "ПИП". Далее идет описание по функциональной электросхеме. "Аккумуляторная батарея" выдает нестабилизированное напряжение постоянного тока номинальной величиной "+12[В]". "+12[В]" поступает на вход блока "Инвертор", из блока "Инвертор" выходит нестабилизированное напряжение переменного тока с параметрами примерно соответствующим стандартам напряжения для потребителей электросетей, это переменное напряжение предназначено для : питания серво- приводов(электромагнитов) бортовых устройств(рулей,тормоза,дросселя), питания сервоприводов целевых устройств. Кроме того, переменное напряжение поступает на вход первого блока вторичного электропитания - "ВИП1". "ВИП1" вырабатывает стабилизированные напряжения постоянного тока "+5[В] №1" и "+12[В] №1" (номиналы); первое напряжение предназначено для питания узлов и блоков : "модуль УЭВМ", "Тахометр", "Термометр", "Радиоприемник системы ДУ", "радиоприемник РНС-ИСЗ "GPS"-"NAVSTAR"; второе предназначено для питания узлов и блоков : "Радиоприемник системы ДУ", "Тахометр", "модуль УЭВМ"(адаптер для RS-232C). "+12[В]" также поступает на вход блока "ВИП2". "ВИП2" вырабатывает стабилизированное напряжение постоянного тока "+5[В] №2" (номинал), предназначенное для питания блока "Модуль драйверов". Блок "ПИП" выдает нестабилизированное напряжение постоянного тока номинальной величи- ной "-12[В]", предназначенное для питания узлов и блоков : "Радиоприемник системы ДУ", "Тахометр", "модуль УЭВМ"(адаптер для RS-232C).

ОПИСАНИЕ РЕШЕНИЯ ПРОБЛЕМЫ ВНУТРЕННИХ ПОМЕХ И НАВОДОК

Здесь идет описание по функциональной электросхеме. Основным источником внутренних наводок являются сервоприводы. Наиболее критичным с точки зрения фатальных(и при этом необративых) сбоев функционирования всего изделия является блок "Мо- дуль УЭВМ". Основным каналом распространения внутренних помех и наводок являются цепи питания. Исходя из вышеперечисленного, "+5[В] №1" , "+12[В] №1" и "-12[В]" гальванически не связаны с остальными уровнями(но разумеется связаны промеж собой). "+12[В]" , " ~220 [B], 50 [Гц]" и "+5[В] №2" - гальванически связаны меж собой. Также используются фильтры низких частот по питанию в блоках "модуль УЭВМ" и "модуль драйверов". И наконец, сами блоки питания также снабжены конденсаторными батареями большой емкости.

ОПИСАНИЕ И ДОПОЛНЕНИЯ (ТЕХНИЧЕСКИЕ ТРЕБОВАНИЯ) К ПРИНЦИПИАЛЬНЫМ ЭЛЕКТРИЧЕСКИМ СХЕМАМ

Вывод 7 ИМС DD4,DD5,DD6,DD7,DD8,DD9,DD10,DD11,DD12,DD13,DD27,DD28,DD29,DD30 подсоединить к цепи "GND". Вывод 14 ИМС DD4,DD5,DD6,DD7,DD8,DD9,DD10,DD11,DD12,DD13,DD27,DD28,DD29,DD30 подсоединить к цепи "VC1". Транзисторы VT1...VT9,VT20...VT27 - на радиаторах. Симисторы VS1...VS16 - на радиаторах. Выводы 62,64 ИМС DD1 подсоединить к цепи "VCC2". Вывод 64 ИМС DD2 подсоединить к цепи "VCC2". Вывод 7 ИМС DD3,DD14,DD15 подсоединить к цепи "GND_CUT". Вывод 14 ИМС DD3,DD14,DD15 подсоединить к цепи "VCC2". Вывод 7 ИМС DD18,DD19 подсоединить к цепи "-7 V". Вывод 14 ИМС DD18,DD19 подсоединить к цепи "+7 V". Вывод 7 ИМС DD20 подсоединить к цепи "GND_CUT". Вывод 14 ИМС DD20 подсоединить к цепи "VCC_CUT". Вывод 7 ИМС DD23,DD24 подсоединить к цепи "-7 V". Вывод 14 ИМС DD23,DD24 подсоединить к цепи "+7 V". Вывод 7 ИМС DD26 подсоединить к цепи "GND_CUT". Вывод 14 ИМС DD26 подсоединить к цепи "VCC_CUT". Выполнить в виде отдельных печатных узлов : модуль УЭВМ, модуль драйверов, тахометр(кроме разумеется магниторезистра R64), радиоприемник системы ДУ(кроме разумеется сото- вого телефона). Печатные платы, используемые в печатных узлах должны быть односторонними. Не допускается монтаж ИМС на панельные разъмы.

РЕЗЮМЕ

Функциональная электросхема реализована в виде принципиальной электросхемы. Реализация имеет несколько недостатков и особенностей.

РЕАЛИЗАЦИЯ ВИРТУАЛЬНОГО АВТОМАТИЧЕСКОГО НАВИГАТОРА(ШТУРМАНА)

Виртуальный автоматический навигатор(штурман) выполняется в DD2. Как известно, точное вождение требует достаточно точного решения навигационной задачи, что в свою очередь требует довольно точных вычислений по формулам аналитической геометрии, включая вычисления в сферической системе координат. В результате, требуется реализовать триганометриче- ские функции, и разумеется вычисления с плавающей точкой, включая умножение. Для таких дел хорошо подходят DSP однокристальные микроЭВМ, но они пока редки в розничной про- даже. Также неплохо бы смотрелся арифметический сопроцессор 8087(80287,80387), но их давно сняли с производства, и поэтому они исчезли.

ИНТЕРФЕЙС МОДУЛЯ УЭВМ

Несколько необычен интерфейс модуля УЭВМ. ОМК ATmega128 имеет мощную периферию(любой контроллер заточен на интенсивный ввод-вывод и содержит аппаратную поддержку разнообразных задач автоматики), но мною реализовано мультипле- ксирование на регистрах сдвига(они в модуле драйверов). Это сделано по двум причинам. Во-первых, экономятся порты ОМК, что позволит в будущем при необходимости модифицировать аппа- ратную часть модуля УЭВМ достаточно малой кровью. Во-вторых, гальваническая развязка получается достаточно компактной. Разумеется, чем-то пришлось поступиться, а именно скоростью ввода-вывода; но это приемлимо, т.к. периферия достаточно медленная.

МОДУЛЬ ДРАЙВЕРОВ

Регистры сдвигов и буферизации использованы "дубовой" 155 серии и к тому же 4-разрядные. Резоны : 1) 155-серии очень много в неликвидах(продаются чуть ли не мешками); 2) У 155-серии выше помехоустойчивость, чем у ТТЛШ серий(555,533,1533), поскольку больше токи; 3) буферные регистры такие же, как и сдвиговые; 4) при желании можно применить мощные драйверы 155ЛА18. С точки зрения помехоустойчивости лучше были бы КМДП-серии(561,564), которые работали бы на 12 вольтах, но они подороже. Вместо обычных симисторов можно было использовать тиристорные оптопары(готовая гальвано- развязка), но они опять-таки подороже.

РАДИОПРИЕМНИК СИСТЕМЫ ДУ

Ставилась задача обойтись как можно меньшими регулировками(вроде удалось совсем от них изба- виться), и при этом в качестве радиочастотной части(антенна,ВЦ,УРЧ,гетеродин,смеситель,УПЧ) использовать как можно более широкий спектр устройств. Поэтому усилитель НЧ сделан неизбирательным(апериодическим) с переменным(дискретным) усилением. УНЧ - хоть и по-сути дела нормирующий, но не логарифимический. В общем АРУ с "мозгами", усиление управляется от ОМК, а фильтрацию(по НЧ для частотного детектирования-деманипуляции) делает по-сути сам ОМК. ATmega8 имеет встроенный компаратор(не говоря об АЦП), но использован внешний ТШ, - для возможности замены ATmega8 на любой другой ОМК(например на 8051).

ТАХОМЕТР

Такая же картина как и в предыдущем пункте. Магниторезистор будет реагировать на пролетающий постоянный магнит, который будет закреплен на валу мотора. Таким образом достигнуто нужное : 1) Бесконтактность; 2) Отсутствие регулировок; 3) Нечувствительность к погрешностям от эксплуатации.

СЕРВОПРИВОДЫ БОРТОВЫХ УСТРОЙСТВ

Выбраны станочные электромагниты на 220 В ввиду их доступности, высокому значению допустимой частоты срабатываний при ПВ=100%, большому тяговому усилию при достаточном ходе(произведение силы на перемещение равно работе), достаточной надежности. Высокое напряжение означает неболь- шой ток(произведение напряжение на ток равно мощности), что позволяет использовать нетолстые провода(пускай изоляция потолще, но пластмасса стоит намного дешевле меди), и к тому же ЭПР машины будет поменьше(а значит ее труднее будет засечь и отследить методами активной радиолокации). Расчет требуемых крутящих моментов на рули будет приведен позднее.

РАДИОПРИЕМНИК РНС-ИСЗ "GPS"-"NAVSTAR"

Выбран тот, который выбран, хотя можно поставить почти любой. Все они имеют примерно похожие параметры, включая интерфейс.

<source lang="cpp">

  1. include <stdio.h>


/*

* Управляющая программа реального времени "Виртуальный_автопилот",
* прошиваемая в однокристальный контроллер ATmega128 (поз. обозн. DD1)
* модуля УЭВМ автоматического мотодельтаплана "АМДП-1".
* Версия №1.
* Начато 06.08.009.
  • /


//...................................................................... // Уровень и характер абстрагирования ориентирован на принц.схему . // Термин "машина" относится к мотодельтаплану "АМДП-1". //...................................................................... void set_begin(void);// функция начальных установок и инициализаций . unsigned char determ_mode(void);// определение текущего режима . unsigned char heating(void); // прогревание мотора . unsigned char starting(void); // разгон машины . unsigned char take_off(void); // взлет машины . unsigned char fly(void); // полет машины . unsigned char landing(void); // посадка машины . unsigned char braking(void); // торможение машины . void measuring(void); // измерения в начале полета . void measuring_course(void); // измерение и формирование ТПФКР . void measuring_forces(void); // измерение и формирование ТПФГ . unsigned char ps_ps_and_cmp_alts(void);// выдача сигналов, пауза и сра-

                                  // внение последовательности высот .

void piloting(void); // пилотирование машины . // определение длительности паузы для текущего газа(в 0.2 сек) : unsigned int tau_gas_F(unsigned char gas, int alt_Lst, int alt_Rq); void course_correction_to_left(void); // коррекция курса влево . void course_correction_to_right(void);// коррекция курса вправо . void alt_correction(void); // коррекция по высоте при отклонении . void descenting(void); // снижение . enum modes {H,S,T,F,L,B}; // режимы . unsigned char present_mode;// текущий режим . enum modes_fly {M,P}; // режимы при полете . unsigned char mode_fly; // текущий режим при полете . unsigned char catch; // индикатор исключ.(нештатн.) ситуации . unsigned char set_down; // флаг режима "посадка"(1 при посадке) . unsigned int time_fst;// показ.счетч.врем. с дискр. 0.2 сек(до 10000 сек) . unsigned int time_slw;// показания счетчика времени с дискретом 10 сек . unsigned int time_lbl_fst1;// метка времени "быстрого" счетчика времени . unsigned int time_lbl_fst2;// метка времени "быстрого" счетчика времени . unsigned int alt_set_land;// высота над уровн.моря (в [м]) точки посадки . unsigned char trigger; // триггер подскока при посадке . unsigned char trigger_1;// триггер касания ВПП при посадке . unsigned int time_lbl_land;// метка времени касания ВПП при торможении . unsigned int alt_req;// требуемая текущая высота над уровнем моря (в [м]),

                    // получаемая от штурмана .

unsigned int alt_last[4];// последние 4 высоты над уровнем моря (в [м]),

                        // [0] - последний по времени, этот массив явля-
                        // ется стеком, его сдвиг - в shturman_int() .

unsigned char d_t;// длительность импульсов с ШИМ на руле тангажа

                 // (период=tau_d_t, шаг_приращения=0.4 сек,
                 //  дискрет_измерения=0.2 сек, макс_знач=3.2 сек) .

unsigned char tau_d_t;// периоды ШИМ на руле тангажа . unsigned char tau_g[4];// длительность изменения высоты (в 0.2 сек)

                      // на один метр при заданном значении газа .

// // Табличная Передаточная Функция Газа (ТПФГ) //----------------------I------------------------------------------- // индекс I 0 1 2 3 //----------------------I------------------------------------------- // знач.газа I "ЕЛЕ-ЕЛЕ" "МАЛЫЙ" "СРЕДНИЙ" "БОЛЬШОЙ" //----------------------I------------------------------------------- // tau_g[] (0.2 сек) I tau_g[0] ... tau_g[3] //----------------------I------------------------------------------- // unsigned int tau_g0_10;// вспомогательная, tau_g0_10=10*tau_g[0],

                      // вычисляется один раз и затем экономится время .

// курс отмеряется от азимута по часовой стрелке . unsigned int course_req;// требуемый курс (в угловых градусах х 100),

                       // получаемый от штурмана .

// последние 10 значений курсов(в угл.градусах х 100), [0] - последний // по времени, этот массив является стеком, его сдвиг - в shturman_int() : unsigned int course_last[10]; int delta_fi;// текущее курсовое отклонение . // длительность импульса на руле курса(шаг_приращения=0.4 сек, // дискрет_измерения=0.2 сек, начальн_знач=0.4 сек, макс_знач=4.8 сек) : const unsigned char D_T1[]={2,4,6,8,10,12,14,16,18,20,22,24}; unsigned char tau[12];// длительность переходного процесса отработки машиной

                     // поворота курсового руля, измеренное в 0.2 сек,
                     // [0] - для D_T1=0.4 сек .

int d_fi[12];// результирующий поворот курса для заданной длительности

            // импульса, измеренный в угл.град. х 100, [0] - для 0.4 сек .

// // Табличная Передаточная Функция Курсового Руля (ТПФКР) //----------------------I--------------------------------------------------- // D_T1[] (0.2 сек) I 2 4 6 8 10 12 14 16 18 20 22 24 //----------------------I--------------------------------------------------- // tau[] (0.2 сек) I tau[0] ... tau[11] //----------------------I--------------------------------------------------- // d_fi[] (угл.гр.х100) I d_fi[0] ... d_fi[11] //----------------------I--------------------------------------------------- // const unsigned char T_1=5;// константа длительности прогрева . const unsigned char T_2=7;// конст.макс.длит. прогрев+разгон . const unsigned char T_3=9;// конст.длит. прогрев+разгон+взлет . const unsigned char DIFFERENCIAL_1=8;// макс.доп.приращ.высоты на взл. . const unsigned char DIFFERENCIAL_2=2;// макс.доп.втор.дифф.высоты на взл. . const unsigned int D_FI_max=300;// (0.01 град) макс.доп.для САУ курсовое от-

                               // клонение, больше - начин.курсовая коррекция .

// (0.01 град) максимальное отклонение соседних по времени // курсов, больше - считаю, что переходный процесс - не завершен : const unsigned int D_FI_meas_tau=100; //............................................................................ // Термин "сигнал" относится к принципиальной схеме ("1",+12,фаза -> "1"). // Считывание сигналов производится раз в сек по прерыванию от DD2, и от DD2. //............................................................................ void put_signals(void);// выдача сигналов . unsigned char signals;// разряды этого байта соответствуют вых.сигналам : // сигнал "ВЛЕВО" -- разряд 0 . // сигнал "ВПРАВО" -- разряд 1 . // сигнал "ВНИЗ" -- разряд 2 . // сигнал "ЕЛЕ-ЕЛЕ" -- разряд 3 . // сигнал "МАЛЫЙ" -- разряд 4 . // сигнал "СРЕДНИЙ" -- разряд 5 . // сигнал "БОЛЬШОЙ" -- разряд 6 . // сигнал "ОСТАНОВ" -- разряд 7 . void put_signal_start(void);// выдача сигнала "ЗАПУСК" . void read_signal_taho(void);// считывание сигналов "TAHO[0,1,2]" . unsigned char taho;// разряды этого байта соотв.входным сигналам : // сигнал "TAHO[0]" -- разряд 0 . // сигнал "TAHO[1]" -- разряд 1 . // сигнал "TAHO[2]" -- разряд 2 . unsigned char start_1,start_2,shassy;// сигналы "ПУСК1","ПУСК2","SHASSY" . // объявление аппаратно зависимых переменных и функций :

  1. include "dcl_hrd"

unsigned char tmp,tmp_1;// tech .


void main(void) {

 // начальная установка внутренних регистров(аппаратно зависимая) :
  1. include "set_rg1"
 set_begin();// начальные установки и инициализации .
 // проверка сигналов "ПУСК1", "ПУСК2" :
 while(1)  {if(start_1==0 && start_2==0){break;} else{;};}
 while(2) {// основной бесконечный цикл .
   present_mode=determ_mode();// опр.тек.режима .
   catch=0;
   switch(present_mode) {// вызов соотв.функции :
     case F : {catch=fly();      break;}// полет .
     case H : {catch=heating();  break;}// прогревание . 
     case S : {catch=starting(); break;}// разгон .
     case T : {catch=take_off(); break;}// взлет .
     case L : {catch=landing();  break;}// посадка .
     case B : {catch=braking();  break;}// торможение .
   }
   if(catch==1 || catch==2)break;// нештатная ситуация на земле .
 }// END OF while(2)
 // установить газ на "ЕЛЕ-ЕЛЕ", включить тормоз :
 signals=0x88;// "1" -> ЕЛЕ-ЕЛЕ ;  "1" -> ОСТАНОВ .

}// END OF main() .

void set_begin(void) {// функция начальных установок и инициализаций .

 present_mode=H;
 mode_fly=M;
 catch=set_down=time_fst=time_slw=time_lbl_fst1=time_lbl_fst2=0;
 alt_set_land=trigger=trigger_1=time_lbl_land=alt_req=0;
 alt_last[0]=alt_last[1]=alt_last[2]=alt_last[3]=0;
 d_t=course_req=delta_fi=tmp=0;  tau_d_t=20;
 tau_g[0]=5;tau_g[1]=10;tau_g[2]=20;tau_g[3]=10;
 tau_g0_10=200;
 course_last[0]=course_last[1]=course_last[2]=course_last[3]=0;
 course_last[4]=course_last[5]=course_last[6]=course_last[7]=0;
 course_last[8]=course_last[9]=0;
 tau[0]=4; tau[1]=6; tau[2]=10; tau[3]=12; tau[4]=16; tau[5]=18;
 tau[6]=22;tau[7]=24;tau[8]=28;tau[9]=30;tau[10]=38;tau[11]=40;
 d_fi[0]=500; d_fi[1]=500; d_fi[2]=800;  d_fi[3]=800;
 d_fi[4]=1000;d_fi[5]=1000;d_fi[6]=1500; d_fi[7]=1500;
 d_fi[8]=2000;d_fi[9]=2000;d_fi[10]=4000;d_fi[11]=6000;
 signals=0x88;// 1 -> "ЕЛЕ-ЕЛЕ" ;  1 -> "ОСТАНОВ" .
 put_signals();

}// END OF set_begin() .

// аппаратно зависимые функции :

  1. include "hrd_dpnd"

unsigned char determ_mode(void) {// определение текущего режима .

 unsigned char grnd;// сигнал "SHASSY" .
 grnd = shassy;
 if(time_slw>=T_3 && set_down==0  && grnd==1)return F;// полет .
 if(time_slw<=T_1 && grnd==0)                return H;// прогревание .
 if(time_slw>T_1  && time_slw<T_3 && grnd==0)return S;// разгон .
 if(time_slw>T_1  && time_slw<T_3 && grnd==1)return T;// взлет .
 if(time_slw>T_3  && set_down==1  && grnd==1)return L;// посадка .
 if(time_slw>T_3  && grnd==0)                return B;// торможение .
 if(time_slw<=1   && grnd==1) {                       // сбой УЭВМ в полете .
   time_slw=T_3+1;mode_fly=P;return F;
 }
 return F;

}

unsigned char heating(void) {// прогревание мотора .

 unsigned int t;// локальное время (0.2 сек) .
 // установить газ на "ЕЛЕ-ЕЛЕ", включить тормоз, включить мотор :
 signals=0x88;// "1" -> ЕЛЕ-ЕЛЕ ;  "1" -> ОСТАНОВ .
 put_signal_start();// включить мотор .
 put_signals();
 t=time_fst; while(time_fst-t<20){;}// ждать 4 сек .
 read_signal_taho();// считывание сигналов "TAHO[0,1,2]"
 if(taho<1) {// если обороты меньше 1(из 7) .
   catch=1;
 }

//======= // ЗАкомментировать строку "printf..." в ICC !!!!! . //=======

 //printf("heating---\n");// tech .
 return catch;

}

unsigned char starting(void) {// разгон машины .

 unsigned int t;// локальное время (0.2 сек) .
 // отключить тормоз, газ на "БОЛЬШОЙ" :
 signals=0x40;// 1 -> "БОЛЬШОЙ" .
 put_signals();
 t=time_fst; while(time_fst-t<20){;}// ждать 4 сек .
 read_signal_taho();// считывание сигналов "TAHO[0,1,2]"
 if(taho<6) {// если обороты меньше 6(из 7) .
   catch=2;
 }

//======= // ЗАкомментировать строку "printf..." в ICC !!!!! . //=======

 //printf("starting---\n");// tech .
 return catch;

}

unsigned char take_off(void) {// взлет .

 unsigned int t;// локальное время (0.2 сек) .
 unsigned char i;// счетчик циклов .
 unsigned char check;// флаг результата проверки дифференциалов .
 char diff_1[3];// первые дифференциалы высот(тангажи) .
 char diff_2[2];// вторые дифференциалы высот .
 t=0;
 // установить руль тангажа в положение "ВНИЗ", газ оставить "БОЛЬШОЙ" :
 signals=0x44;// 1 -> "ВНИЗ" ;  1 -> "БОЛЬШОЙ" .
 put_signals();
 t=time_fst; while(time_fst-t<d_t){;}// ждать d_t (0.2 сек) .
 // уст.руль тангажа в гориз.положение, газ оставить "БОЛЬШОЙ" :
 signals=0x40;// 1 -> "БОЛЬШОЙ" .
 put_signals();
 t=time_fst;
 while(time_fst-t<tau_d_t-d_t){;}// ждать (tau_d_t-d_t) (0.2 сек) .
 // вычисление тангажей и их дифференциалов :
 for(i=0;i<3;i++) diff_1[i]=alt_last[i]-alt_last[i+1];
 for(i=0;i<2;i++) diff_2[i]=diff_1[i]-diff_1[i+1];
 // проверка их :
 check=0;
 for(i=0;i<3;i++) if(diff_1[i]>DIFFERENCIAL_1) check=1;
 for(i=0;i<2;i++) if(diff_2[i]>DIFFERENCIAL_2) check=1;
 // если дифференциалы не вышли за допустимые и длительность импульсов
 // не больше максимальной, то увеличить длительность импульсов :
 if(check==0 && d_t<=16)d_t=d_t+2;
 else {d_t=d_t-2;catch=3;}// иначе уменьшить .
 // сменить период, во избежание самовозбуждения(резонанса) :
 switch(tau_d_t) {
   case 20:{tau_d_t=26;break;} case 26:{tau_d_t=20;break;}
 }

//======= // ЗАкомментировать строку "printf..." в ICC !!!!! . //=======

 //printf("take_off---\n");// tech .
 return catch;

}// END OF take_off() .

unsigned char fly(void) {// полет .

 if(mode_fly==M) measuring();
 if(mode_fly==P) piloting();

//======= // ЗАкомментировать строку "printf..." в ICC !!!!! . //=======

 //printf("fly---\n");// tech .
 return catch;

}

void measuring(void) {// измерения .

 unsigned int t;// локальное время .
 // газ в "СРЕДНИЙ", рули в неактивное состояние :
 signals=0x20;// 1 -> "СРЕДНИЙ";
 put_signals();
 t=time_fst; while(time_fst-t<20){;}// ждать 4 сек .
 measuring_course();// измерение и формирование ТПФКР .
 measuring_forces();// измерение и формирование ТПФГ .
 mode_fly=P;// теперь можно начать пилотирование .

}

void measuring_course(void) {// измерение и формирование ТПФКР .

 unsigned int t;// локальное время (0.2 сек) .
 unsigned char j;// счетчик циклов .
 int i;// счетчик циклов .
 // i - счетчик порядкового номера курса(10 - за последние 10 секунд) .
 // j - счетчик порядкового номера длительности импульса .
 // цикл по значениям длительностей импульсов,
 // D_T1[] = 2, 4, 6, 8, 10, ... , 24 (0.2 сек) :
 for(j=0;j<12;j++) {
   // установить курсовой руль "ВЛЕВО", газ оставить в "СРЕДНИЙ" :
   signals=0x21;// 1 -> "ВЛЕВО" ;  1 -> "СРЕДНИЙ";
   put_signals();
   t=time_fst; while(time_fst-t<D_T1[j]){;}// ждать D_T1[j] (0.2 сек) .
   // газ оставить в "СРЕДНИЙ", рули в неактивное состояние :
   signals=0x20;// 1 -> "СРЕДНИЙ";
   put_signals();
   t=time_fst; while(time_fst-t<50-D_T1[j]){;}// ждать 50-D_T1[j] (0.2 сек) .
   // длительность переходного процесса :
   for(i=8;i>=0;i--) {// последние 10 курсов - сравниваю соседние :
     // если два соседних совпадают до D_FI_meas_tau(0.01 град),
     // то переходный процесс - завершен :
     if(course_last[i]-course_last[i+1]<D_FI_meas_tau ||
        course_last[i+1]-course_last[i]<D_FI_meas_tau)
     {tau[j]=(9-i)*5;break;}// фиксирую длительность перех.проц. .
   }
   // результирущий поворот курса для данной длительности импульса :
   d_fi[j]=course_last[0]-course_last[9];
   if(d_fi[j]<0)d_fi[j]=-d_fi[j];// модуль
   if(d_fi[j]>4500)break;// если поворот больше 45 град., то достаточно .
 }

}// END OF measuring_course() .

void measuring_forces(void) {// измерение и формирование ТПФГ .

 // рули при этом - в неактивное состояние .
 // газ на "БОЛЬШОЙ" :
 signals=0x40;// 1 -> "БОЛЬШОЙ" .
 tau_g[3]=ps_ps_and_cmp_alts();
 // газ на "СРЕДНИЙ" :
 signals=0x20;// 1 -> "СРЕДНИЙ" .
 tau_g[2]=ps_ps_and_cmp_alts();
 // газ на "МАЛЫЙ" :
 signals=0x10;// 1 -> "МАЛЫЙ" .
 tau_g[1]=ps_ps_and_cmp_alts();
 // газ на "ЕЛЕ-ЕЛЕ" :
 signals=0x8;//  1 -> "ЕЛЕ-ЕЛЕ" .
 tau_g[0]=ps_ps_and_cmp_alts();
 tau_g0_10=10*tau_g[0];// вспомогательно, чтобы не тратить время потом .

}// END OF measuring_forces() .

unsigned char ps_ps_and_cmp_alts(void) {// выдача сигналов, пауза и

                                   // сравнение последовательности высот .
 unsigned int t;// локальное время (0.2 сек) .
 put_signals();
 t=time_fst; while(time_fst-t<30){;}// ждать 6 сек .
 // это сравнение избыточно, но оставь для широкой совместимости :
 if(alt_last[0]>alt_last[1]) {tmp_1=alt_last[0]-alt_last[1];}
 else                        {tmp_1=alt_last[1]-alt_last[0];}
 switch(tmp_1) {// здесь, tmp_1 - скорость снижения в [м/сек] .
   case 0:{tmp=5;break;} case 1:{tmp=4;break;} case 2 :{tmp=3;break;} 
   case 3:{tmp=2;break;} case 4:{tmp=1;break;} default:{tmp=1; break;}
 }
 if(alt_last[0]==alt_last[3])return 15;
 if(alt_last[0]==alt_last[2])return 10;
 return tmp;

}

void piloting(void) {// пилотирование машины .

 // если высота текущая ниже требуемой
 // на 10м и более, то выполнять взлет :
 if(alt_req>alt_last[0]+10){catch=take_off();return;}
 // если высота текущая больше требуемой
 // на 10м и более, то выполнять снижение :
 if(alt_req+10<alt_last[0])descenting();
 // если высота текущая отличается от требуемой, но не более,
 // чем на 10м, то выполнить коррецию траектории по высоте :
 if(alt_req!=alt_last[0] && alt_req-alt_last[0]<=10 &&
    alt_last[0]-alt_req<=10){
 alt_correction();// коррекция по высоте при отклонении .
 }
 delta_fi=course_last[0]-course_req;// текущее курсовое отклонение .
 // если текущее курсовое отклонение больше D_FI_max(0.01 град),
 // то выполнить коррецию влево :
 if(delta_fi>D_FI_max){course_correction_to_left();return;}
 // если текущее курсовое отклонение меньше -D_FI_max(0.01 град),
 // то выполнить коррецию вправо :
 if((-delta_fi)>D_FI_max){course_correction_to_right();return;}

}// END OF piloting() .

void descenting(void) {// снижение

 unsigned int t;// локальное время (0.2 сек) .
 // рули при этом - в неактивное состояние .
 // газ на "ЕЛЕ-ЕЛЕ" :
 signals=0x8;//  1 -> "ЕЛЕ-ЕЛЕ" .
 put_signals();
 // tau_g0_10 - длит.снижения(в 0.2 сек) на 10 м, посчитано ранее .
 t=time_fst;while(time_fst-t<tau_g0_10){;}// ждать tau_g0_10(0.2 сек) .

}// END OF descenting() .

void alt_correction(void) {// коррекция по высоте при отклонении

 //рули при этом - в неактивное состояние .
 unsigned int t;// локальное время (0.2 сек) .
 unsigned int tau_gas;// (0.2 сек)длительность паузы для текущего газа .
 unsigned char gas;// текущее значение газа,
                   // 1000 - "БОЛЬШОЙ", 0100 - "СРЕДНИЙ",
                   // 0010 - "МАЛЫЙ",   0001 - "ЕЛЕ-ЕЛЕ" .
 gas = (signals>>3) & 0xF;// выявить текущее значение газа .
 // если происходило понижение, и текущая высота больше требуемой,
 // то оставить газ прежним :
 if(alt_last[0]<alt_last[1] && alt_last[0]>alt_req) {;}
 // если происходило понижение, и текущая высота меньше требуемой,
 // то прибавить газ на шаг :
 if(alt_last[0]<alt_last[1] && alt_last[0]<alt_req) {
   switch (gas) {// увеличение на один шаг текущего газа :
     case 1 : gas=2;// "ЕЛЕ-ЕЛЕ" -> "МАЛЫЙ"
     case 2 : gas=4;// "МАЛЫЙ"   -> "СРЕДНИЙ"
     case 4 : gas=8;// "СРЕДНИЙ" -> "БОЛЬШОЙ"
   }
   signals = gas<<3;
   put_signals();
 }
 // если происходило повышение, и текущая высота больше требуемой,
 // то сбавить газ на шаг :
 if(alt_last[0]>alt_last[1] && alt_last[0]>alt_req) {
   switch (gas) {// уменьшение на один шаг текущего газа :
     case 2 : gas=1;// "МАЛЫЙ"   -> "ЕЛЕ-ЕЛЕ"
     case 4 : gas=2;// "СРЕДНИЙ" -> "МАЛЫЙ"
     case 8 : gas=4;// "БОЛЬШОЙ" -> "СРЕДНИЙ"
   }
   signals = gas<<3;
   put_signals();
 }
 // если происходило повышение, и текущая высота меньше требуемой,
 // то оставить газ прежним :
 if(alt_last[0]>alt_last[1] && alt_last[0]<alt_req) {;}
 // определение длительности паузы для текущего газа(0.2 сек) :
 tau_gas=tau_gas_F(gas,alt_last[0],alt_req);
 // пауза установленной длительности(при этом с установленным газом) :
 t=time_fst;while(time_fst-t<tau_gas){;}

}// END OF alt_correction() .

// определение длительности паузы для текущего газа(0.2 сек) : unsigned int tau_gas_F(unsigned char gas, int alt_Lst, int alt_Rq) {

 // alt_Lst-текущая высота, alt_Rq-требуемая высота .
 unsigned int tmp1;
 int tmp2;
 tmp2=alt_Lst-alt_Rq; if(tmp2<0)tmp2=-tmp2;
 switch (gas) {
   case 1 : tmp1=tau_g[0]*tmp2;// "ЕЛЕ-ЕЛЕ"
   case 2 : tmp1=tau_g[1]*tmp2;// "МАЛЫЙ"
   case 4 : tmp1=tau_g[2]*tmp2;// "СРЕДНИЙ"
   case 8 : tmp1=tau_g[3]*tmp2;// "БОЛЬШОЙ"
 }
 return tmp1;

}

void course_correction_to_left(void) {// курсовая коррекция влево

 unsigned int t;//  (0.2 сек)локальное время .
 unsigned char i;// локальный счетчик циклов .
 // опр.индекс в табл.длительностей импульсов руля :
 for(i=0;i<11;i++)if(delta_fi>d_fi[i] && delta_fi<d_fi[i+1])break;
 // установить курсовой руль "ВПРАВО" :
 signals=signals & 0xFE;// 0 -> "ВЛЕВО" .
 signals=signals | 0x2;//  1 -> "ВПРАВО" .
 put_signals();
 t=time_fst; while(time_fst-t<D_T1[i]){;}// ждать D_T1[i] 0.2 сек .
 // установить курсовой руль в нейтраль :
 signals=signals & 0xFD;//    0 -> "ВПРАВО" .
 put_signals();
 // ждать (tau[i]-D_T1[i]) 0.2 сек :
 t=time_fst; while(time_fst-t<(tau[i]-D_T1[i])){;}

}// END OF course_correction_to_left() .

void course_correction_to_right(void) {// курсовая коррекция вправо

 unsigned int t;// локальное время .
 unsigned char i;// локальный счетчик циклов .
 delta_fi=-delta_fi;// сделать положительным
 // опр.индекс в табл.длительностей импульсов руля :
 for(i=0;i<11;i++)if(delta_fi>d_fi[i] && delta_fi<d_fi[i+1])break;
 // установить курсовой руль "ВЛЕВО" :
 signals=signals | 0x01;//    1 -> "ВЛЕВО" .
 signals=signals & 0xFD;//    0 -> "ВПРАВО" .
 put_signals();
 t=time_fst; while(time_fst-t<D_T1[i]){;}// ждать D_T1[i] 0.2 сек .
 // установить курсовой руль в нейтраль :
 signals=signals & 0xFE;// 0 -> "ВЛЕВО" .
 put_signals();
 // ждать (tau[i]-D_T1[i]) 0.2 сек :
 t=time_fst; while(time_fst-t<(tau[i]-D_T1[i])){;}

}// END OF course_correction_to_right() .

unsigned char landing(void) {// посадка .

 // схему посадки смотри в описании от 01.08.2009 .
 unsigned int t;// локальное время .
 // рули - в неактивное состояние,
 // газ на "ЕЛЕ-ЕЛЕ" :
 signals=0x8;//  1 -> "ЕЛЕ-ЕЛЕ" .
 // если текущая высота <= 2м (над точкой посадки),
 // то (один раз) газ на "БОЛЬШОЙ" и пауза в 1 сек :
 if(alt_last[0]-alt_set_land<=2 && trigger==0) {
   signals=0x40;// 1 -> "БОЛЬШОЙ" .
   put_signals();
   trigger=1;
   t=time_fst; while(time_fst-t<5){;}// ждать 1 сек .
 }
 put_signals();
 delta_fi=course_last[0]-course_req;// текущее курсовое отклонение .
 // если текущее курсовое отклонение больше 10 град,
 // то выполнить коррецию влево :
 if(delta_fi>1000){course_correction_to_left();return 4;}
 // если текущее курсовое отклонение меньше -10 град,
 // то выполнить коррецию вправо :
 if(delta_fi<-1000){course_correction_to_right();return 4;}

//======= // ЗАкомментировать строку "printf..." в ICC !!!!! . //=======

 //printf("landing---\n");// tech .
 return 0;

}// END OF landing() .

unsigned char braking(void) {// торможение .

 // зафиксировать время касания ВПП :
 if(trigger_1==0){time_lbl_land=time_fst;trigger_1=1;}
 // рули - в неактивное состояние,
 // газ на "ЕЛЕ-ЕЛЕ" :
 signals=0x8;//  1 -> "ЕЛЕ-ЕЛЕ" .
 // через две секунды включить тормоз :
 if(time_fst-time_lbl_land>10) {
   signals=signals | 0x80;//   1 -> "ОСТАНОВ" .
 }
 put_signals();
 delta_fi=course_last[0]-course_req;// текущее курсовое отклонение .
 // если текущее курсовое отклонение больше 10 град,
 // то выполнить коррецию влево :
 if(delta_fi>1000){course_correction_to_left();return 5;}
 // если текущее курсовое отклонение меньше -10 град,
 // то выполнить коррецию вправо :
 if(delta_fi<-1000){course_correction_to_right();return 5;}

//======= // ЗАкомментировать строку "printf..." в ICC !!!!! . //=======

 //printf("braking---\n");// tech .
 return 0;

}// END OF braking() .

</source>