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

Материал из roboforum.ru Wiki
Перейти к: навигация, поиск


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

Электрические схемы и спецификации

Для просмотра схем и чертежей используйте 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>

Примечания