Проект Мегапират на самик!
Нашел я траблу в 26 прошивке, по инверту при холоде… Хоть ее походу только я и юзаю, но все же может кому интересно:
Трабла в библиотеке “RC_Channel.cpp”:void
RC_Channel::set_reverse(bool reverse)
{
if (reverse) _reverse = -1;
else _reverse = 1;
}bool
RC_Channel::get_reverse(void)
{
if (_reverse==-1) return 1;
else return 0;
}Честно говоря не понимаю что изменяет переменные при холоде, но если закоментить изменение, глюк исчезает…
Вы немного не то нашли. То, что Вы нашли просто ставит каналу поле реверс в определённое значение, в зависимости от параметра (bool reverse), ну и возвращает текущее состояние, зареверсен канал или нет. Сам этот код понятия не имеет ни о температурных коррекциях ни о прочих высоких материях. Он просто меняет значение своей внутренней переменной в зависимости от входного параметра. Вам нужно найти другой код, который собственно говоря и дёргает этот set_reverse() с неправильным (с Вашей точки зрения) значением. Киньте ссылку на СВН, где Вы этот код взяли, если не засну раньше времени – можно покопаться.
26- я версия валяется тут
…googlecode.com/…/MegaPiratePlane2.26.zip
Вы немного не то нашли.
Я же написал что не нашел что изменяет сие значения при холоде, но сей код устраняет данное явление, что для меня и являлось главной задачей 😃 Мне не надо чтоб при каких то событиях кроме настроек, сервы переходили в режим инверта, особенно в полете 😃
Ну а если найдете место где именно меняются “высокие материи”, буду вам очень признателен 😃
Ну а если найдете место где именно меняются “высокие материи”, буду вам очень признателен
Под рукой кроме Нотепада ничего нет. 8( Посмотрел на код из zipа …googlecode.com/…/MegaPiratePlane2.26.zip . Текстовым поиском найти вызов напрямую set_reverse во всём том количестве исходных файлов из-за какой-то температурной коррекции пока не удалось.
Если Вы уверены, что реверс появляется постепенно от холода, а не в связи с параметрами из конфигурации, будем рыть дальше.
Пошёл с другой стороны, надеюсь уважаемый Syberian быстрее поймёт оно это или не оно, бо нормальной иде у меня нет да и со структурой классов\алгоритмами ещё не разбирался.
Итак, в config.h есть определение такой вот константы
#ifndef HIL_MODE
#define HIL_MODE HIL_MODE_DISABLED
#endif
Шо за HIL – не знаю, мабудь это какой-то АрдуПилотовский термин.
Дальше, в MegaPiratePlane.pde есть вот такой фрагмент кода, который объявит переменную imu как экземпляр класса AP_IMU_Oilpan (бо HIL_MODE=HIL_MODE_DISABLED):
#if HIL_MODE != HIL_MODE_ATTITUDE
#if HIL_MODE != HIL_MODE_SENSORS
// Normal
AP_IMU_Oilpan imu(&adc, Parameters::k_param_IMU_calibration);
#else
// hil imu
AP_IMU_Shim imu;
#endif
// normal dcm
AP_DCM dcm(&imu, g_gps);
#endif
Вот у этого AP_IMU_Oilpan в методе update() дёргается
/**************************************************/
// Returns the temperature compensated raw gyro value
//---------------------------------------------------
float
AP_IMU_Oilpan::_sensor_in(uint8_t channel, int adc_value)
{
float adc_in;
// get the compensated sensor value
//
adc_in = adc_value;
// adjust for sensor sign and apply calibration offset
//
if (_sensor_signs[channel] < 0) {
adc_in = _sensor_cal[channel] - adc_in;
} else {
adc_in = adc_in - _sensor_cal[channel];
}
return adc_in;
}
Так вот, метод _sensor_in() и возвращает “термоскорректированные” показания гироскопа (Returns the temperature compensated raw gyro value).
Сам этот imu вроде как дёргается из DCM в методах DCM.update_DCM() и DCM.update_DCM_fast.
В конструкторе DCM инициируется на основе imu// Constructors
AP_DCM(IMU *imu, GPS *&gps, Compass *withCompass = NULL)
Ну а сами методы DCM.update_DCM() и DCM.update_DCM_fast() дёргаются из основного MegaPiratePlane.pde на каждой итерации.
Т.е. имеем цепочку вызовов MegaPiratePlane->DCM.update_DCM()->AP_IMU_Oilpan.update()->AP_IMU_Oilpan._sensor_in().
Либо же “fast” цепочку MegaPiratePlane->DCM.update_DCM_fast()->AP_IMU_Oilpan.update()->AP_IMU_Oilpan._sensor_in().
Не суть важно, ибо обе цепочки приводят к одному методу _sensor_in(), который собственно говоря и возвращает “термоскорректированные” показания гироскопа.
Если я правильно отследил цепочку, то тут уже вопрос к уважаемому Syberian, правильно ли _sensor_in() работает. Если правильно, тогда, наверно, надо смотреть на то, откуда берутся эти “компенсационные” данные для этого метода _sensor_in() , т.е. _sensor_signs[channel] и _sensor_cal[channel]. Сил без нормальной ИДЕ разбираться в этом у меня пока нет. Нотепад всё высосал 8).
и возвращает “термоскорректированные” показания гироскопа
Это оно и есть, и это как показывает практика работает как надо, фишка в том что в планере как я уже писал показывает все правильно, “горизонт” не куда не уплывает и тд тп, тобишь гироскоп и акселерометры работают по правильным алгоритмам, и если в них есть термокомпенсация, то она работает верно.
Описанный мной глюк влияет именно на “реверс” серв, который вылезал при охлаждении… Думаю тут больше “глюк” портирования, и какая то переменная лезет куда ей лезть не следует 😃 А вот вычислить сие место крайне проблематично, закоментив сам блок “перехода” глюк уходит, с моими познаниями аурдино вычислить, что откуда в хитрых переплетениях между основным кодом и библиотеками пирата…
Посмотрел на код
К стати если вы хороший знаток аурдино, хотелось бы пустить ваш порыв в нужном направлении 😉 Есть мысли откуда вылазит “кривая” скорость? Если посмотреть ветку выше, можно найти мной выложенные ролики полета, где скорость кажет в районе 250 😃 Но в то же время мелькает иногда и правильная… опять же где то идет перезапись нужной переменной… Есть мысли где сие может происходить?
К стати гуру, кто как отлаживает код в аурдино??? Есть какой то софт, чтоб пройтись по коду, посмотреть переменные и тд тп? А то как то в слепую все, что то закодил, а что там дальше крутится хз…
Нашел еще одно интересное место…
if (inverted_flight) nav_pitch = -nav_pitch;
Тобишь каким то образом можно врубить инверт и самуль якобы будет лететь верх тормашками, а рулиться как в обычном полете… Походу это дело и происходит, при холоде по какой то причине включается этот режим, и все рули естественно начинают работать в инверте?
Леонид, к сожалению, я не знаток Ардуино. Как и АрдуПилота\Вортекса. Для меня это всё тот же AVR с кучкой припаяных датчиков-- гироскопы, аксели и т.д. К стати, поздравьте, совратился я МегаПиратом и Вортексом, купил www.ebay.com/itm/260854008499 Что повеселило – прямо написано MEGA Pirate and MultiWii code compatible. 😃
Теперь о плохом. После знакомства с ИДЕ Ардуино – культурный шок, в худшем смысле этого слова. Единственный эпитет – убожество. Не, я понимаю, что избалован Эклипсом, Идеей, да даже Вижуал Студией, на худой конец. Но такое… Иногда мне кажется, что банальный Notepad++ или SciTe более функционален чем ИДЕ Ардуино. Средств отладки в ИДЕ Ардуино непредусмотренно. Единственный вариант --из кода программы выводить на каждой итерации в COM-порт всю дебажную информацию, а с компа любым сериал-терминалом смотреть, хоть тем же Serial Monitor из ИДЕ Ардуино.
Короче, начал я смотреть код Пирата в ИДЕ Ардуино – удобства не намного больше, чем с обычным Нотепадом. Будем тихонько смотреть.
Нашел я откуда лезут реверсы:
if (!g.switch_enable) {
// switches are disabled in EEPROM (see SWITCH_ENABLE option)
// this means the EEPROM control of all channel reversal is enabled
return;
}
// up is reverse
// up is elevon
g.mix_mode = (PINL & 128) ? 1 : 0; // 1 for elevon mode
if (g.mix_mode == 0) {
g.channel_roll.set_reverse((PINE & 128) ? true : false);
g.channel_pitch.set_reverse((PINE & 64) ? true : false);
g.channel_rudder.set_reverse((PINL & 64) ? true : false);
} else {
g.reverse_elevons = (PINE & 128) ? true : false;
g.reverse_ch1_elevon = (PINE & 64) ? true : false;
g.reverse_ch2_elevon = (PINL & 64) ? true : false;
}
Но почему это происходит по изменению температуры для меня так и остается загадкой…
Что касается inverted_flight – найти где он ставится проблемы нету, это происходит только в одном месте. По умолчанию inverted_flight=false.
И только в control_modes.pde в методе read_control_switch() он переставляется:
static void read_control_switch()
{
......
if (g.inverted_flight_ch != 0) {
// if the user has configured an inverted flight channel, then
// fly upside down when that channel goes above INVERTED_FLIGHT_PWM
inverted_flight = (control_mode != MANUAL && APM_RC.InputCh(g.inverted_flight_ch-1) > INVERTED_FLIGHT_PWM);
}
}
Т.е., если пользователь сконфигурировал с компа какой-то канал как “инвертированный”, то inverted_flight поменяет своё значение при условии, что пепелац сейчас управляется не вручную и значение этого управляющего канала превысло INVERTED_FLIGHT_PWM , т.е. 1750 (
define INVERTED_FLIGHT_PWM 1750
).
Не знаю, говорит ли Вам это о чём-то, но общий смысл достаточно прост-- если с вашего пульта пришла команда по какому-то сконфигурированному Вами каналу на вход Вортексу больше чем 1750 и в это время пепелац летел на автопилоте–МегаПират принимает решения, что у Вас inverted_flight .
static void read_control_switch()
{
…
if (g.inverted_flight_ch != 0) {
// if the user has configured an inverted flight channel, then
// fly upside down when that channel goes above INVERTED_FLIGHT_PWM
inverted_flight = (control_mode != MANUAL && APM_RC.InputCh(g.inverted_flight_ch-1) > INVERTED_FLIGHT_PWM);
}
}
Это все коментил, переход в инверт на морозе оставался.
Глюк пропадает только когда коментишь вот этот кусок:
g.channel_roll.set_reverse((PINE & 128) ? true : false);
g.channel_pitch.set_reverse((PINE & 64) ? true : false);
g.channel_rudder.set_reverse((PINL & 64) ? true : false);
Честно говоря не совсем понимаю что здесь происходит…?
но общий смысл достаточно прост-- если с вашего пульта пришла команда по какому-то сконфигурированному Вами каналу на вход Вортексу больше чем 1750 и в это время пепелац летел на автопилоте–МегаПират принимает решения, что у Вас inverted_flight
Вот только не пойму, ЗАЧЕМ??? Тут не происходит класического “полета в инверте” (АП переворачивает самуль и удерживает его в таком положении) - НЕТ! При данном переключении самуль закрутится юлой и по тангажу и крену и по любасу рухнет…
Режим самоуничтожения 😃?
К стати Олег, понял в чем идет скорость 😃
g_gps->ground_speed * rot.a.x, // X speed cm/s
Тобишь 250 = 25 м/с 😃 Теперь будет крайне легко преобразовать сие дело в удобночитаемую циферу 😃
Ндя, что то под вечер с математикой моей стало 😃))
Леонид, ща времени нет порыться посмотреть, что такое PINE и PINL. Если предположить, что это Port E и Port L Меги 2560, тогда надо порыться и посмотреть на схеме BlackVortex, что у него подключено к соответствующим ножкам этих портов:
(PINE & 128)
(PINE & 64)
(PINL & 64)
П.С. А где схема… Блин, на ЕБее даже ссылки нету, надо искать… 😵
П.П.С. 250 = 25 м/с – не вкурил. 😃
кто как отлаживает код в аурдино???
Да никак его не отладить. Только на плате через ком-порт что-то выводить.
По поводу inverted flight. Он включается через какой-то канал приемника. У тебя случайно он не разрешен?
прямо написано MEGA Pirate and MultiWii code compatible.
Велкам в нестройные ряды пиратов 😃 Покупать надо было на csgshop.com, там на 20 баксов дешевле.
Чтобы не ломать глаз в блокноте, используйте Notepad++, там есть подсветка синтаксиса.
Для поиска текста по всему проекту пользуюсь FAR manager 1.63 - типа нортона под виндой.
Глюк пропадает только когда коментишь вот этот кусок:
ага, попался! Я понял в чем засада. Дело в том, что в оригинальном ардупилоте за реверсы отвечают микропереключатели на плате. У нас их, естественно, нет, и эти ноги висят в воздухе. К тому же, на них нет подвески, т.е. все наводки и конденсат наши. В 2.24 они просто запрещены, а 2.26 была первая пробная версия, в которую я это не перенес (забыл).
За скорость отдельное спасибо 😃
П.П.С. 250 = 25 м/с – не вкурил.
Отписался уже, что туплю под вечер 😃 Один ноль потерял 😃 В общем, гипотеза по скорости провалилась…
Чисто предположу, что инверсия происходит когда происходит переполнение больше 16 бит.
К тому же, на них нет подвески, т.е. все наводки и конденсат наши.
Вот оно в чем дело, ну хоть все встало на свои места, что радует 😃 А по скорости очень похоже на правду что это метры в секунду / 10. Хотя смотрю у тебя уже стоит преобразование в км/ч на выход в еОСД… Чтот мое запуталось однако 😃
sport.write((byte)(g_gps->ground_speed * 0.036));
Чисто предположу, что инверсия происходит когда происходит переполнение больше 16 бит.
Тогда почему сие не происходит при комнатной температуре ни при каких условиях?
Велкам в нестройные ряды пиратов Покупать надо было на csgshop.com, там на 20 баксов дешевле.
Чтобы не ломать глаз в блокноте, используйте Notepad++, там есть подсветка синтаксиса.
Для поиска текста по всему проекту пользуюсь FAR manager 1.63 - типа нортона под виндой.
Пасиб 😃 Про csgshop.com – не знал, спасибо, на будущее запомню. Линку брал то ли с чьего-то блога, то ли с начала этой темы. Про ЦСГШоп там не было. 😦
По поводу Notepad++ – я его уже года 2 использую, как и SciTe. Много вещей в них делать удобнее чем в Eclipse( в основном, я Java Enterprise разработчик). А файловый менеджер уже нное количество лет – Total Commander. Тока не будем разжигать религиозную войну Far Vs TC. 😌
Олег, возвращаясь к моему предыдущему посту:
1)
PINE и PINL. Если предположить, что это Port E и Port L Меги 2560
Правильно ли это предположение?
2)
посмотреть на схеме BlackVortex, что у него подключено к соответствующим ножкам этих портов:
(PINE & 128) (PINE & 64) (PINL & 64)
Выходит, что к 6й, 7й ножке порта Е и 6й ножке порта L подключались те самые
оригинальном ардупилоте за реверсы отвечают микропереключатели на плате.
?
П.С. И ссылкой на схему BV не поделитесь?
П.С. И ссылкой на схему BV не поделитесь?
Думаю схему не кто не даст, как то тут уже писалось, мол это ком. тайна и все такое 😃
Отписался уже, что туплю под вечер 😃 Один ноль потерял 😃 В общем, гипотеза по скорости провалилась…
Не всё так плохо 😃
defines.h содержит константу предела скорости, при которой автопилот начнёт отрыв от земли
#define SPEEDFILT 400 // centimeters/second; the speed below which a groundstart will be triggered
По mavlinkу тоже
g_gps->ground_speed * rot.a.x, // X speed cm/s
g_gps->ground_speed * rot.b.x, // Y speed cm/s
В том же config.h
#ifndef AIRSPEED_CRUISE
# define AIRSPEED_CRUISE 12 // 12 m/s
#endif
#define AIRSPEED_CRUISE_CM AIRSPEED_CRUISE*100 – специально переводят себе в cm/s
Идём дальше AP_DCM.cpp (хреновина, которая всё и решает 😃):
#define SPEEDFILT 300 // centimeters/second
radio.pde тоже оперирует cm/s
Так что Ваше предположение о том, что внутри МегаПират оперирует сантиметрами/сек скорее всего верно.
Да, если bvHUD – ответная часть для ОСД: sport.write((byte)(g_gps->ground_speed*0.036)); //m/s *100 transform to KPH
Если _EOSD – ответная часть для какой-то другой ОСД sport.write((byte)(g_gps->ground_speed*0.036));
Т.е. то же самое cm/s переводят в km/h
Значит у МегаПилота всё нормально. Особенно, учитывая тот факт, что g_gps->ground_speed используется в МП везде.
Если показывается в ОСД другое значение – надо тогда смотреть код самой ОСД, скорее всего он неправильно отмалёвывает. Или неправильно вынимает то, что ему приходит от bvHUD или _EOSD части МегаПилота.
Выходит, что к 6й, 7й ножке порта Е и 6й ножке порта L подключались те самые оригинальном ардупилоте за реверсы отвечают микропереключатели на плате.
“Пробил” только что схему оригинального ардупилота. Таки да, переключатели реверсов подключены к ногам соответствующих портов контроллера -
PL6 - 41
PL7 - 42
PE6 - 8
PE7 - 9
П.С. И ссылкой на схему BV не поделитесь?
Схема Вортекса - Мега 2560 + датчики в стандартном подключении. По пдфкам с его сайта достаточно хорошо видно разводку верхней стороны платы. Ничего, кроме задействованных в Пирате ног там дополнительно не разведено. В т.ч. и эти ноги тоже не разведены. Я себе развёл свою плату, аналогичного функционала, только ЖПС вынес отдельно. Жду датчики, чтобы собрать и проверить в работе:)
Да, по поводу нашего БлекВортекса и единиц измерения скорости в МегаПирате.
У нас стоит U-Blox ГПС, скорость вынимается из MSG_VELNED их протокола. А там единицы измерения чётко указаны
velN cm/s NED north velocity
8 I4 - velE cm/s NED east velocity
12 I4 - velD cm/s NED down velocity
16 U4 - speed cm/s Speed (3-D)
20 U4 - gSpeed cm/s Ground Speed (2-D)
Так что Леонид Вы правы, МегаПират оперирует cm/s
PL6 - 41
PL7 - 42
PE6 - 8
PE7 - 9
Отлично, что подтвердилось. Теперь по коду стало намного проще понимать, что такое PINE и PINL.