Транспортный авиационный робот
Источники: [1] Обсуждение на форуме
Содержание
- 1 ЭЛЕКТРИЧЕСКИЕ СХЕМЫ И СПЕЦИФИКАЦИИ
- 1.1 СХЕМА ЭЛЕКТРИЧЕСКАЯ СТРУКТУРНАЯ
- 1.2 СХЕМА ЭЛЕКТРИЧЕСКАЯ ФУНКЦИОНАЛЬНАЯ
- 1.3 СХЕМЫ ЭЛЕКТРИЧЕСКИЕ ПРИНЦИПИАЛЬНЫЕ
- 1.3.1 ОПИСАНИЕ ВНЕШНИХ СИГНАЛОВ МОДУЛЯ УЭВМ
- 1.3.2 КОМАНДЫ РАДИОУПРАВЛЕНИЯ
- 1.3.3 ОПИСАНИЕ ВНУТРЕНИХ СИГНАЛОВ МОДУЛЯ УЭВМ
- 1.3.4 ОПИСАНИЕ СИГНАЛОВ МОДУЛЯ ДРАЙВЕРОВ
- 1.3.5 ОПИСАНИЕ СИГНАЛОВ БОРТОВЫХ СЕНСОРОВ
- 1.3.6 ОПИСАНИЕ ЭЛЕКТРОПИТАНИЯ
- 1.3.7 ОПИСАНИЕ РЕШЕНИЯ ПРОБЛЕМЫ ВНУТРЕННИХ ПОМЕХ И НАВОДОК
- 1.3.8 ОПИСАНИЕ И ДОПОЛНЕНИЯ (ТЕХНИЧЕСКИЕ ТРЕБОВАНИЯ) К ПРИНЦИПИАЛЬНЫМ ЭЛЕКТРИЧЕСКИМ СХЕМАМ
- 1.3.9 РЕЗЮМЕ
ЭЛЕКТРИЧЕСКИЕ СХЕМЫ И СПЕЦИФИКАЦИИ
Для просмотра схем и чертежей используйте 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">
- 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" . // объявление аппаратно зависимых переменных и функций :
- include "dcl_hrd"
unsigned char tmp,tmp_1;// tech .
void main(void) {
// начальная установка внутренних регистров(аппаратно зависимая) :
- 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() .
// аппаратно зависимые функции :
- 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>