Квадрокоптер на Arduino своими руками|

Квадрокоптер на Arduino своими руками| Самолеты

Введение

Теперь, когда вы выбрали все основные компоненты для вашего БПЛА, вы можете приступать к сборке. В этом руководстве будут рассмотрены распространенные ошибки при сборке многороторного БПЛА, а также приведены некоторые полезные советы по настройке. Этот урок не будет охватывать такие элементы, как камера/FPVсистема, дальнобойные устройства или другие аксессуары (рассмотрим на 7 уроке).

Компоненты, которые вы должны иметь на этом этапе:

  1. Рама (купленная или исполненная вручную)
  2. Моторы, ESC, пропеллеры, аккумулятор, зарядное устройство
  3. Плата распределения питания/соединительные жгуты
  4. Контроллер полёта и устройство связи (предложено радиоуправление)

Квадрокоптер на Arduino своими руками|

Силовая установка

Для достижения целей этого урока, силовая установка вашего БПЛА будет включать следующие компоненты:

  • Моторы
  • ESC
  • Распределение питания (плата или соединительные жгуты)
  • Аккумуляторная батарея
  • Полётный контроллер

Обратите внимание, что пропеллеров в списке нет. Не устанавливайте пропеллеры на данном этапе! Несущие винты будут подключены только на 6 уроке. Поскольку это ваш первый беспилотник, мы рекомендуем выполнить «безрамное» подключение электрической части, перед тем, как установить всё на раму; с целью проверить все соединения и устранить выявленные неисправности.

Аккумулятор. распределение питания

Соединение между аккумулятором и системой распределения питания должно быть относительно простым, если они оба имеют одинаковый тип разъёма. Если это так, то переходите к следующему шагу. Если же разъёмы разные, то не в коем случае не перерезайте провода аккумулятора для отделения разъёма; это может вызвать короткое замыкание и неприятный удар током! Вместо этого вы можете подобрать переходник и использовать его между разъёмом на АКБ и разъёмом платы распределения питания. Другим вариантом может выступать поиск ответного разъёма к разъёму АКБ, и его покупка; затем отрежьте существующий разъём от распределителя питания и припаяйте купленную замену, предварительно убедившись в отсутствии связи между положительным и отрицательным контактами.

Важно отметить, что большинство мультироторных БЛА не имеют переключателя вкл/выкл, поэтому питание подаётся и отключается путем подключения и отсоединения основной батареи от разъёма распределителя питания, поэтому их разъемы должны быть надёжно закреплены, а провода/точки пайки хорошо изолированы посредством термоусадочной трубки и/или изолентой.

Прежде чем продолжить, отсоедините аккумулятор от распределителя питания.

Квадрокоптер на Arduino своими руками|

Мотор. esc. распределение питания

Плата распределения питания (ПРП) или проводное распределение в первую очередь служат для распределения питания от основной батареи к каждому ESC. Напряжение подается на ESC «как есть», поэтому нет необходимости повышать (увеличивать) или понижать (уменьшать) напряжение. Если ваш беспилотник имеет четыре двигателя, то у вас должно быть четыре ESC, и, следовательно, ваша распределительная плата/проводное распределение должны в конечном итоге разделить основную батарею на четыре соединения. Если же ваша ПРП имеет шесть подключений, а вы собираете квадрокоптер, то вам просто не нужно подключать последние два. Если вы строите гексакоптер, ваша ПРП должна распределить питание от основной батареи на шесть соединений. ESC включает в себя следующие провода:

  • Один 3-проводной 0.1-дюймовый шлейф с R/C разъёмом, в числе которых чёрный контакт обычно является заземлением, красный обеспечивает 5В выход (через BEC*), а жёлтый/белый является входом сигнала.
  • Три раздельных провода служат для подключения к трём проводам на бесколлекторном моторе постоянного тока (обычно поставляются с разъёмами типа «пуля» с внутренней резьбой, которые либо уже припаяны, либо включены в комплект).
  • Два входных разъёма для подключения аккумулятора к PDB (некоторые включают паяные разъёмы с пайкой, какие-то входят в комплект, а бывает вообще не входят).

*ESC обычно имеют встроенную цепь устранения батареи (или BEC), которая преобразует напряжение основной батареи в 5В для последующего питания приёмника и контроллера полёта. 5В обычно подаётся через RC разъём от ESC (обычно центральный/красный контакт). Вам потребуется только один BEC для питания контроллера полёта.

Квадрокоптер на Arduino своими руками|

Если плата распределения питания использует разъёмы, которые не совпадают с разъёмами на ESC или АКБ, то вам нужно будет, либо приобрести переходники (адаптеры), либо приобрести новые разъёмы и заменить их на ESC или ПРП. Преимущество остаётся за платой распределения питания, разъёмы которой совпадают с разъёмами АКБ и ESC. Чаще всего литий-полимерная аккумуляторная батарея БЛА может иметь DEANS разъём, XT60 или EC3.

Если вы хотите запитать дополнительную слаботочную электронику (светодиодную систему освещения, подвесное устройство и т.д.), но на вашей плате распределения питания нет запасных соединений, вы можете использовать зарядный кабель аккумуляторной батареи. Белый зарядный разъём обычно имеет один контакт для заземления и по одному контакту для каждой банки (1S, 2S, 3S и т.д.) используемой в сборке LiPo АКБ. Несмотря на то, что этот разъём действительно предназначен только для зарядки батареи, он может обеспечивать выходное напряжение равное 3.7В от каждого контакта и может использоваться для питания слаботочной электроники, такой как подвесная система или светодиоды.

Квадрокоптер на Arduino своими руками|

  1. Удалите красный повод у каждого 3-контактного R/C разъёма регулятора скорости, за исключением одного. Рекомендуется это сделать таким образом, чтобы при необходимости вы всегда могли подключить их обратно. Замотайте конец каждого исключённого провода изолентой или используйте для изоляции термоусадочную трубку, чтобы в последствии они не смогли контактировать с другими элементами электроники. Тот единственный красный провод, что остался не тронутым, будет питать используемый в сборке полётный контроллер.
  2. Подключите два питающих провода каждого ESC к распределительной плате, убедившись, что красный провод подводится к плюсу ( ), а чёрный провод к минусу (-).
  3. Если используемая вами плата распределения питания имеет свои R/C разъёмы, то в данном случае решать вам, подключать R/C выводы каждого ESC к R/C разъёмам на этой плате или подключать их напрямую к полётному контроллеру.
  4. Подсоедините каждый из трёх разъёмов моторов к трём разъёмам регуляторов скорости (ESC). На данный момент порядок подключения этих разъёмов не важен (если повлияет на направление вращения, то будет исправлено по мере необходимости позднее).

Обратите внимание, что если вы решите на данном этапе убрать или скрыть проводку, позднее вам может потребоваться доступ к некоторым соединениям в соответствии с процедурой, описанной в 6 уроке, в частности, поменять местами соединения между ESC и мотором, чтобы двигатель вращался в противоположном направлении.

Квадрокоптер на Arduino своими руками|

Esc. контроллер полёта.

Сейчас вы можете подключить R/C входы регуляторов скорости к контроллеру полёта. Выбранный вами контроллер полёта должен иметь схему, в которой показано, к каким контактам контроллера подключаются моторы вашей мультироторной сборки. Также в этой схеме должно быть показано направление вращения каждого мотора, но, опять же, пока вам не нужно учитывать направление.

  1. Ознакомьтесь со схемой подключения между моторами/ESC и полётного контроллера в руководстве по эксплуатации ПК.
  2. Подключите R/C разъёмы каждого ESC к соответствующим контактам полётного контроллера, убедитесь, что провод заземления (обычно чёрный) подключается к контакту заземления контроллера полёта, а сигнальный контакт (белый или желтый) подключается к сигнальному контакту на контроллере полёта.
  3. Только один из RC разъёмов будет по-прежнему иметь красный (питающий) контакт.

Квадрокоптер на Arduino своими руками|

Связь

Приёмник. полётный контроллер.

Предположим, что на этом уроке вы сделали выбор в пользу радиоуправления в качестве устройства ввода. Если вы хотите использовать WiFi, Bluetooth или другой способ ввода, пожалуйста, прочитайте инструкцию по контроллеру полёта и найдите последовательный ввод; в этом разделе будет описано, как/куда подключить устройство последовательного ввода к контроллеру полёта. Скорее всего, вам потребуется найти и подключить передающее (Tx), принимающее (Rx), напряжение (5В) и GND-контакты от беспроводного устройства к передатчику, обеспечивая Rx от одного к Tx другого, и наоборот.

Ваш RC передатчик должен приходить в комплекте с соответствующим RC приёмником. Приёмник должен быть привязан к передатчику, чтобы вы могли удалить перемычку привязки с приёмника (если она есть). В комплект также может входить держатель АА батарейки, которая предназначена для питания приёмника, но мы не будем использовать её, поскольку BEC будет питать как приёмник, так и контроллер полёта. Чтобы узнать, какие каналы RC приёмника подключаются к каким контактам на контроллере полёта, вам нужно взглянуть на руководство пользователя как контроллера полёта, так и RC системы.

В руководстве к контроллеру полёта будут указаны местоположения следующих контактов, которые должны быть согласованы и подключены к приёмнику:

  • Throttle
  • Pitch
  • Yaw
  • Roll
  • Вспомогательные (Aux) переключатели 1, 2, 3 и т.д.

Квадрокоптер на Arduino своими руками|

Теперь вы можете сделать следующие подключения:

  1. Прочитайте руководство к контроллеру полёта, чтобы увидеть, какой входной R/C контакт связан с какой из перечисленных выше функций.
  2. Прочтите руководство к передатчику, чтобы узнать, какой канал связан с каждой из функций.
  3. Некоторые RC передатчики могут быть перепрограммированы для изменения функций каждого контакта. Если вы решите изменить какой нибудь вход (джойстик или переключатель), делайте это лишь после того, как убедитесь, что знаете, какой канал на приёмнике соответствует какой функции. Throttle, Pitch, Yaw, и Roll всегда должны быть связаны с двумя стиками/джойстиками, а не с переключателями или кнопками.
  4. Подключите канал Throttle на приёмнике к входу Throttle на контроллере полёта.
  5. Подключите канал Pitch на приёмнике к входу Pitch на контроллере полёта.
  6. Подключите канал Yaw на приёмнике к входу Yaw на контроллере полёта.
  7. Подключите GND на контроллере полёта (обычно третий ряд контактов) к GND на приёмнике (обычно третий ряд контактов).
  8. Если будет использоваться вспомогательный вход, подключите Aux 1 на приёмнике к Aux 1 на контроллере полёта и так далее.

Вы можете использовать 3-контактные серво провода для каждого из каналов, но только один из каналов (может быть любым) должен иметь напряжение и заземление; остальным нужен только сигнальный провод. Все соединения могут иметь GND к GND, хотя требуется только одно. Еще раз, приёмнику не нужна отдельная батарея, поскольку он будет получать питание от контроллера полёта, который получает питание от BEC от одного из ESC.

Сборка рамы

Если вы строите свою собственную раму, вы можете собрать её на этом этапе. Если вы приобрели рамный комплект, следуйте инструкции по сборке. Обратите внимание, что вам может потребоваться разобрать определенные участки, чтобы облегчить подключение или убрать (скрыть) элементы электрики. Цель заключается в том, чтобы гарантировать, что ничто не ослаблено, все провода надёжно закреплены, и ничто не может выпасть из рамы или запутаться.

Квадрокоптер на Arduino своими руками|

Монтаж

Размещение акб.

Батарея, используемая для питания, часто является самым тяжелым элементом на БПЛА и может составлять от 1/4 до 1/2 его общего веса. Поэтому, место её установки очень важно. Идеальное расположение основного аккумулятора должно быть в центре коптера, чтобы все двигатели могли выдерживать примерно одинаковую нагрузку. Если аккумулятор расположен ближе к задней части коптера, задние моторы должны будут обеспечивать большую тягу, чем моторы спереди, и, соответственно, максимальная общая тяга будет ограничена (когда задние двигатели находятся на полной тяге, на моторах спереди тяги не будет). Принимая во внимание, что обычный подход в мультироторной конструкции состоит в том, чтобы коптер был симметричен относительно центральной оси (или, по крайней мере, одной оси), поэтому батарею следует размещать вдоль этой центральной линии, а не смещать ее в одну или другую сторону.

Далее вам нужно будет решить, на какой высоте разместить аккумулятор. Есть несколько мест, где батарея может быть установлена:

  1. Под рамой (коптер будет тяжелым снизу, более стабильным и менее акробатичным).
  2. Прямо под моторами (обычно внутри рамы); возможно, одно из лучших мест.
  3. На той же высоте, что и двигатели или несущие винты (например, устанавливается в верхней части рамы).
  4. Над пропеллерами (БПЛА будет сверху тяжелым и более склонным к перевороту).

Для достижения наилучших лётных характеристик, в идеале АКБ должна быть расположена в положении 3, описанном выше. Положение 4 создает эффект перевернутого маятника, и, если БПЛА наклонится за пределы определенного угла, то дрон будет стремиться к перевороту. Положение 1 создаст достаточно стабильную платформу, которая по своей природе склонна оставаться на одном уровне, но при этом крайне не годится для акробатики. Поэтому большинство разработчиков выбирают положение 2 и размещают аккумулятор либо непосредственно под рамой, либо внутри нее. Такой подход освобождает пространство под рамой для полезной нагрузки, такой как система подвеса, а пространство выше для контроллера полёта и другой электроники, чтобы они были максимально доступны.

Квадрокоптер на Arduino своими руками|

Монтаж батареи

Существует множество общепринятых способов крепления батареи к раме, которые включают в себя:

  • Ремни с липучкой
  • Самоклеющаяся липучка (одна сторона клеится на АКБ, а другая на раме)
  • В раме

Ремни с липучкой являются наиболее распространенными для пользовательских дронов среднего «стандартного» размера, тогда как заключение в раме чаще всего встречается на коммерческих беспилотниках, рамы таких БЛА зачатую отливаются под давлением и оставляют внутри пространство специально под определенный аккумулятор. Липучки в идеале следует использовать только в том случае, если батарея относительно лёгкая; вместо одного короткого отрезка в центре, рекомендуется клеить одну полосу по всей длине батареи. Если вы используете ремни на липучке и обнаруживаете, что батарея склонна к выдвиганию из-за отсутствия сцепления, рекомендуется добавлять резиновые полоски в места, где батарея контактирует с ремнями. Не рекомендуется использовать клей для крепления аккумулятора к раме. Если вы не используете БЛА, извлеките АКБ и храните её в безопасной LiPo сумке (LiPo safe bag) или керамическом резервуаре.

Зарядка акб

Весьма вероятно, что вы выбрали литий-полимерный (LiPo) или другой литиевый аккумулятор. Большинство LiPo аккумуляторов свыше 3.7В имеют для зарядки отдельный кабель с многоконтактным разъёмом, в то время как силовой кабель можно определить по наличию двухконтактного разъёма с более крупными проводами, способными выдерживать большой ток разряда. Разъём для зарядки обычно имеет по одному контакту для каждой банки батареи, а также общий контакт заземления.

Из-за опасностей, связанных с LiPo батареями (водород и электричество), обычной практикой является полное извлечение батареи из дрона, когда она не используется, и помещение ее в безопасную сумку «LiPo Safe». Эта же сумка используется при зарядке батареи (подключите батарею к зарядному устройству, поместите батарею в сумку (оставив зарядное устройство вне сумки) и закройте её (обычно в ней есть клапан с липучкой).

Размещение и монтаж контроллера полёта

В идеале контроллер полёта должен быть расположен в центре дрона на той же высоте, что и моторы. Если это невозможно, то контроллер можно поставить чуть выше или ниже. Не стоит устанавливать контроллер полёта больше в направлении левой или правой стороны, и избегайте установки его со сдвигом вперед или назад. Если вы приобрели раму для БПЛА, то у таких зачастую есть монтажные отверстия для контроллера полёта, которые находятся в оптимальном месте. Контроллер полёта может быть закреплен любым из следующих основных способов:

  • Винты/Гайки /Стойки (основные)
  • Двухсторонняя клейкая лента (убедитесь, что она достаточно прочная)
  • Двусторонняя клейкая пена (для достижения демпфирующего эффекта)
  • Резиновые демпфирующие втулки (для значительного демпфирования)

Некоторые полётные контроллеры либо имеют, либо могут иметь опционально защитный кейс. Этот корпус защищает печатную плату от пыли и нескольких капель дождя и может принять на себя удар в случае краша. В некоторых случаях используются резиновые демпферы/втулки, которые уменьшают вибрацию, вызванную несбалансированными моторами/пропеллерами. Идеальная сборка — макс. жесткая рама с идеально сбалансированной силовой установкой и хорошо изолированным от вибраций контроллером полёта.

Квадрокоптер на Arduino своими руками|

Размещение и монтаж esc

ESC подключаются между моторами, распределительной платой/кабелем и контроллером полёта. Стандартная длина проводов ESC и моторов, как правило не требует их удлинения в процессе сборки мультиротора. ESC должны обеспечивать высокий ток и, соответственно могут сильно нагреваться в процессе эксплуатации. Идеальное расположение регулятора находится непосредственно под лопастями несущего винта на опорном луче; такой подход обеспечит ему хорошее охлаждение. ESC может быть прикреплен к опоре с помощью стяжек (по одной на каждой стороне ESC), ленты или почти любым другим способом, который не будет препятствовать отводу тепла. ESC не должны устанавливаться в месте, ограничивающем рассеивание тепла (например, в закрытой металлической коробке), и должны располагаться на расстоянии от чувствительной электроники, такой как контроллер полёта или приёмник.

Квадрокоптер на Arduino своими руками|

Rc приёмник и антенна

Сам RC приёмник может быть расположен почти в любом месте на беспилотнике. Исключением являются места находящиеся в непосредственной близости с силовыми проводами (подальше от АКБ и ESC). Приёмники, входящие в состав RC-систем, как правило, не имеют какого-либо конкретного способа монтажа, поэтому качественный двухсторонний клей является лучшим вариантом.

Квадрокоптер на Arduino своими руками|

Антенна, которая крепится к приёмнику, обычно представляет собой гибкий провод. Этот провод должен быть расположен таким образом, чтобы ничего не мешало приёму сигнала. Её можно закрепить либо вдоль опорного луча (с противоположной стороны от ESC), либо вдоль посадочной опоры. На 6 уроке мы поговорим больше о тестировании дальности, которое должно быть сделано, чтобы узнать максимальное расстояние, на котором приёмник принимает сигнал от передатчика. Тестирование дальности может потребовать, чтобы вы поэкспериментировали с разными местами расположения приёмника и антенны.

Размещение и монтаж gps-антенны

В отличие от проводной антенны приёмника, антенна GPS приёмника имеет тенденцию быть либо «Duck» антенной (жёсткий пластиковый зафиксированный столбик, 90 градусов или навесной), либо прямоугольной и относительно плоской. Некоторые GPS устройства имеют встроенную антенну (то есть антенна является частью печатной платы). В любом случае GPS антенна должна быть установлена в верхней части БПЛА, чтобы спутниковые сигналы не блокировались. Монтаж прямоугольной антенны обычно выполняется с помощью двухсторонней ленты, а монтаж «Duck» антенны обычно включает в себя сверление монтажных отверстий. Если «Duck» антенна подключается непосредственно к контроллеру полёта, то никакого дополнительного монтажа не требуется.

На данном этапе у вас должен быть полностью собранный и подключённый БПЛА, за исключением пропеллеров. 6 урок включает настройку и тестирование передатчика, программного обеспечения контроллера полёта, предполётную проверку и первый полёт.

Устройство бортового компьютера

Компоненты устройства:1. Платформа Arduino2. Модуль гироскопа акселерометра высотомера3. Модуль записи на SD-карте SD-карта4. Батарея питания5. Тумблер отключения питания6. Кнопка для сброса высоты7. Светодиоды-индикаторы взвода и зажигания8. Реле для замыкания внешней цепи при зажигании9. Несколько резисторов, указанных на схеме

Принципы работы устройства:1. Устройство непрерывно замеряет текущую высоту с помощью датчика высоты, и вычисляет среднее значение за последние 16 измерений — скользящее среднее (это нужно для сглаживания колебаний измерения, так как они довольно сильно «скачут»).2.

Если нажата кнопка сброса высоты, текущее скользящее среднее высоты берётся в качестве начала отсчёта, и, в дальнейшем измеряется так называемая «высота от точки старта» — это высота за вычетом данного начала отсчёта. Соответственно, в месте, где кнопка была нажата, будет 0 этой высоты.3.

В ходе вычислений замеряется максимальная «высота от точки старта», после достижения которой 10 метров (например), устройство переходит в состояние «взвод», максимальная высота продолжает замеряться (любая измеренная высота больше максимальной — объявляется новой максимальной), при этом зажигается светодиод взвода4.

Если, находясь в состоянии «взвод» замерянная высота окажется меньше максимальной на 1 метр (например), устройство переходит в состояние «запуск», замыкая реле, и зажигая светодиод запуска. Светодиод взвода при этом гасится. Реле может выполнить любую работу, например, подать напряжение на сервопривод, выпускающий парашют.5.

Общая схема подключения компонентов:

Модули, необходимые для приложения:

Для работы программы я собрал несколько библиотек, либо не входящих в репозиторий Arduino, либо других версий, которые удалось заставить работать.

Библиотека BMP085:BMP085.cppBMP085.h

Библиотека HMC5883LHMC5883L.cppHMC5883L.h

Библиотека I2CI2Cdev.cpp I2Cdev.h

Библиотека MPU6050MPU6050.cpp MPU6050.h

Все эти модули можно найти вместе с основным файлом программы в репозитории.

Код приложения:

#include <Wire.h>#include "BMP085.h"#include "I2Cdev.h"#include "MPU6050.h"#include "HMC5883L.h"#include <SPI.h>#include <Wire.h>#include "BMP085.h"#include "I2Cdev.h"#include "MPU6050.h"#include "HMC5883L.h"#include <SPI.h>#include <SD.h>
 
#define TRUE 1#define FALSE 0
 
File myFile;
 
HMC5883L compass;
BMP085 pressure_m;
MPU6050 accelgyro;
 
//Контакт, куда подключено рэле#define EXEC_PIN 3//Контакт, куда подключена кнопка "сброс высоты"#define RESET_ALT_PIN 6//Контакт, куда подключен светодиод "взвод" (красный)#define ARMED_PIN 9//Время в течении которого надо держать рэле замкнутым, в миллисекундах#define FIRE_TIME 6000//Количество итераций для вычисления скользящего среднего высоты (лучше, чтобы было степенью двойки)#define RUN_ALT_NUM 16
 
//Контакт, куда подключена кнопка "положение X"#define POS_X_PIN 7//Контакт, куда подключена кнопка "положение Y"#define POS_Y_PIN 8//Контакт, куда подключена кнопка "положение Z"#define POS_Z_PIN 10
 
 
int16_t ax, ay, az;int16_t gx, gy, gz;
bool blinkState =false;double dt =;long counter =;double t0 =-1;double millis_t =;double io_t =;double io_dt =40;double fired_millis_t =;
 
float base_altitude =;
 
float run_alt[RUN_ALT_NUM];int run_alt_index =;int last_run_alt_index =;int run_alt_count =;float run_alt_summ =;
 
bool is_prepared = FALSE;
bool is_armed = FALSE;
bool is_fired = FALSE;
bool is_led_armed = FALSE;
bool is_led_fired = FALSE;
bool is_done = FALSE;
 
float arming_altitude =10;float fire_minus_altitude =1;float max_altitude =;
 
char filename[]="GY88_000.TXT";
 
void reset_running_alt();void reset_alt(float current_alt);
 
/**
 * Сгенерировать имя файла
 */void generateFileName(){for(int i =; i<1000; i){
    filename[5]= i/100'0';
    filename[6]=(i%100)/10'0';
    filename[7]=(i%10)'0';if(SD.exists(filename))continue;
    Serial.print("File: ");
    Serial.println(filename);break;}}
 
/**
 * Отладочная функция, вычисляет сумму скользящего среднего "по-настоящему"
 */float debug_get_alt_summ(){float summ =;for(int i=; i< run_alt_count; i){
    summ  = run_alt[i];}return summ;}
 
void setup(){//Настраиваем режимы работы для цифровых контактов
    pinMode(EXEC_PIN, OUTPUT);
    pinMode(RESET_ALT_PIN, INPUT);
    pinMode(ARMED_PIN, OUTPUT);//Сбрасываем значения для скользящего среднего по высоте
    reset_running_alt();
 
    //Включаем последовательный порт на максимальную скорость
    Serial.begin(230400);//while (!Serial) {;// wait for serial port to connect. Needed for native USB port only//}    
 
    Serial.print("Initializing SD card...");
 
    if(!SD.begin(4)){
      Serial.println("initialization failed!");return;}
    Serial.println("initialization done.");
 
    //Сгенерируем имя файла
    generateFileName();
    myFile = SD.open(filename, O_WRITE | O_CREAT);
 
    //Включаем протокол Wire
    Wire.begin();
    TWBR =24;
    Serial.println("Initializing I2C devices...");//инициализируем акселерометр с гироскопом
    accelgyro.initialize();
    accelgyro.setMasterClockSpeed(13);
    accelgyro.setI2CMasterModeEnabled(true);//инициализируем компас
    compass = HMC5883L();
    setupHMC5883L(); 
 
    //проверяем содеинение
    Serial.println("Testing device connections...");
    Serial.println(accelgyro.testConnection()?"MPU6050 connection successful":"MPU6050 connection failed");
 
    //калибруем датчик давления
    pressure_m.bmp085Calibration();}
 
void loop(){
  millis_t = millis();//Считаем температуру (её знает датчик давления)float temperature = pressure_m.bmp085GetTemperature();//MUST be called first//Считаем давлениеfloat pressure = pressure_m.bmp085GetPressure();//Вычислим высоту над уровнем моряfloat altitude = pressure_m.calcAltitude(pressure);float altitude_b = altitude - base_altitude;
 
  //Проведём вычисления для скользящего среднего по высоте
  run_alt[run_alt_index]= altitude_b;//run_alt_summ  = altitude_b;if(run_alt_count == RUN_ALT_NUM){
    last_run_alt_index =(run_alt_index ==)? RUN_ALT_NUM -1: run_alt_index -1;//run_alt_summ -= run_alt[last_run_alt_index];}else{
    run_alt_count  =1;}
  run_alt_index =(run_alt_index 1== RUN_ALT_NUM)?: run_alt_index 1;
 
  //Временно вычисляем медленным методом
  run_alt_summ = debug_get_alt_summ();
 
  float run_altitude = run_alt_summ /(float) run_alt_count;
 
  //Вычислим dt (интервал между замерами в миллисекундах)if(t0 <){
    t0 = millis_t;}else{
    dt = millis_t - t0;
    t0 = millis_t;}
 
  if(run_altitude > max_altitude){
    max_altitude = run_altitude;}
 
 
  if(millis_t - io_t > io_dt){
    io_t = millis_t;if(digitalRead(RESET_ALT_PIN)== HIGH){
      reset_alt(altitude);}
 
 
 
    if(!is_done){if(!is_fired){if(is_prepared){if(!is_armed){if(max_altitude > arming_altitude){
              is_armed = TRUE;}}else{if(max_altitude - run_altitude > fire_minus_altitude){
              is_armed = FALSE;
              is_fired = TRUE;
              fired_millis_t = millis_t;}}}}else{if(millis_t - fired_millis_t > FIRE_TIME){
          is_fired = FALSE;
          is_done = TRUE;
          is_prepared = FALSE;}}}
 
    if(is_armed != is_led_armed){
      is_led_armed = is_armed;
      digitalWrite(ARMED_PIN, is_armed ? HIGH : LOW);}
 
    if(is_fired != is_led_fired){
      is_led_fired = is_fired;
      digitalWrite(EXEC_PIN, is_fired ? HIGH : LOW);}
 
  }
 
  //Интервал между замерами
  Serial.print("dt:"); Serial.print(dt /1000,3);
  myFile.print("dt:"); myFile.print(dt /1000,3);//Сколько времени прошло с запуска?
  Serial.print(" tm:"); Serial.print(millis_t);
  myFile.print(" tm:"); myFile.print(millis_t);//Температура, в градусах цельсия
  Serial.print(" t:"); Serial.print(temperature,2); 
  myFile.print(" t:"); myFile.print(temperature,2);//Давление, в паскалях
  Serial.print(" p:"); Serial.print(pressure,); 
  myFile.print(" p:"); myFile.print(pressure,);//Высота над уровнем моря, в метрах
  Serial.print(" alt:"); Serial.print(altitude,2); 
  myFile.print(" alt:"); myFile.print(altitude,2);//Высота над базовым уровнем, в метрах
  Serial.print(" altb:"); Serial.print(altitude_b,2); 
  myFile.print(" altb:"); myFile.print(altitude_b,2);//Высота над базовым уровнем, в метрах, скользящее среднее
  Serial.print(" altr:"); Serial.print(run_altitude,2); 
  myFile.print(" altr:"); myFile.print(run_altitude,2);//Высота над базовым уровнем, в метрах, максимальная
  Serial.print(" Malt:"); Serial.print(max_altitude,2); 
  myFile.print(" Malt:"); myFile.print(max_altitude,2);
 
  //Статусы:
  Serial.print(" P"); Serial.print(is_prepared ?"1":"0"); 
  myFile.print(" P"); myFile.print(is_prepared ?"1":"0");
  Serial.print(" A"); Serial.print(is_armed ?"1":"0"); 
  myFile.print(" A"); myFile.print(is_armed ?"1":"0");
  Serial.print(" F"); Serial.print(is_fired ?"1":"0"); 
  myFile.print(" F"); myFile.print(is_fired ?"1":"0");
  Serial.print(" D"); Serial.print(is_done ?"1":"0"); 
  myFile.print(" D"); myFile.print(is_done ?"1":"0");
 
  //Считаем значения с магнитометра
  MagnetometerScaled scaled = compass.ReadScaledAxis();//Считаем значения с акселерометра и гироскопа
  accelgyro.getMotion6(&ax,&ay,&az,&gx,&gy,&gz);
 
  //Данные акселерометра:
  Serial.print(" ax:"); Serial.print(ax);
  Serial.print(" ay:"); Serial.print(ay);
  Serial.print(" az:"); Serial.print(az);
  myFile.print(" ax:"); myFile.print(ax);
  myFile.print(" ay:"); myFile.print(ay);
  myFile.print(" az:"); myFile.print(az);//Данные гироскопа
  Serial.print(" wx:"); Serial.print(gx);
  Serial.print(" wy:"); Serial.print(gy);
  Serial.print(" wz:"); Serial.print(gz);
  myFile.print(" wx:"); myFile.print(gx);
  myFile.print(" wy:"); myFile.print(gy);
  myFile.print(" wz:"); myFile.print(gz);//Данные магнитометра    
  Serial.print(" cx:"); Serial.print(scaled.XAxis,3);
  Serial.print(" cy:"); Serial.print(scaled.YAxis,3);
  Serial.print(" cz:"); Serial.print(scaled.ZAxis,3);
  Serial.println();
  myFile.print(" cx:"); myFile.print(scaled.XAxis,3);
  myFile.print(" cy:"); myFile.print(scaled.YAxis,3);
  myFile.print(" cz:"); myFile.print(scaled.ZAxis,3);
  myFile.println();
 
  myFile.flush();}
 
//Настройка модуля HMC5883L (компаса)void setupHMC5883L(){//Setup the HMC5883L, and check for errorsint error;  
  error = compass.SetScale(1.3);//Set the scale of the compass.if(error !=) Serial.println(compass.GetErrorText(error));//check if there is an error, and print if so
 
  error = compass.SetMeasurementMode(Measurement_Continuous);// Set the measurement mode to Continuousif(error !=) Serial.println(compass.GetErrorText(error));//check if there is an error, and print if so}
 
/**
 * Сброс высоты и перевод в состояние готовности - выполняется по нажатию кнопки
 */void reset_alt(float current_alt){
  base_altitude = current_alt;
  is_prepared = TRUE;
  is_armed = FALSE;
  max_altitude =;  
  reset_running_alt();}
 
/**
 * Сброс скользящего среднего для высоты
 */void reset_running_alt(){
  run_alt_index =;
  run_alt_count =;
  run_alt_summ =;
  last_run_alt_index =;for(int i =; i<RUN_ALT_NUM; i){
      run_alt[i]=;}}

#include <Wire.h>
#include “BMP085.h”
#include “I2Cdev.h”
#include “MPU6050.h”
#include “HMC5883L.h”
#include <SPI.h>
#include <Wire.h>
#include “BMP085.h”
#include “I2Cdev.h”
#include “MPU6050.h”
#include “HMC5883L.h”
#include <SPI.h>
#include <SD.h>

#define TRUE 1
#define FALSE 0

File myFile;

HMC5883L compass;
BMP085 pressure_m;
MPU6050 accelgyro;

//Контакт, куда подключено рэле
#define EXEC_PIN 3
//Контакт, куда подключена кнопка “сброс высоты”
#define RESET_ALT_PIN 6
//Контакт, куда подключен светодиод “взвод” (красный)
#define ARMED_PIN 9
//Время в течении которого надо держать рэле замкнутым, в миллисекундах
#define FIRE_TIME 6000
//Количество итераций для вычисления скользящего среднего высоты (лучше, чтобы было степенью двойки)
#define RUN_ALT_NUM 16

//Контакт, куда подключена кнопка “положение X”
#define POS_X_PIN 7
//Контакт, куда подключена кнопка “положение Y”
#define POS_Y_PIN 8
//Контакт, куда подключена кнопка “положение Z”
#define POS_Z_PIN 10

int16_t ax, ay, az;
int16_t gx, gy, gz;
bool blinkState = false;
double dt = 0;
long counter = 0;
double t0 = -1;
double millis_t = 0;
double io_t = 0;
double io_dt = 40;
double fired_millis_t = 0;

float base_altitude = 0;

float run_alt[RUN_ALT_NUM];
int run_alt_index = 0;
int last_run_alt_index = 0;
int run_alt_count = 0;
float run_alt_summ = 0;

bool is_prepared = FALSE;
bool is_armed = FALSE;
bool is_fired = FALSE;
bool is_led_armed = FALSE;
bool is_led_fired = FALSE;
bool is_done = FALSE;

float arming_altitude = 10;
float fire_minus_altitude = 1;
float max_altitude = 0;

char filename[] = “GY88_000.TXT”;

void reset_running_alt();
void reset_alt(float current_alt);

/**
* Сгенерировать имя файла
*/
void generateFileName()
{
for (int i = 0; i< 1000; i )
{
filename[5] = i/100 ‘0’;
filename[6] = (i0)/10 ‘0’;
filename[7] = (i) ‘0’;
if (SD.exists(filename)) continue;
Serial.print(“File: “);
Serial.println(filename);
break;
}
}

/**
* Отладочная функция, вычисляет сумму скользящего среднего “по-настоящему”
*/
float debug_get_alt_summ()
{
float summ = 0;
for (int i=0; i< run_alt_count; i )
{
summ = run_alt[i];
}
return summ;
}

void setup(){
//Настраиваем режимы работы для цифровых контактов
pinMode(EXEC_PIN, OUTPUT);
pinMode(RESET_ALT_PIN, INPUT);
pinMode(ARMED_PIN, OUTPUT);
//Сбрасываем значения для скользящего среднего по высоте
reset_running_alt();

//Включаем последовательный порт на максимальную скорость
Serial.begin(230400);
//while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
//}

Serial.print(“Initializing SD card…”);

if (!SD.begin(4)) {
Serial.println(“initialization failed!”);
return;
}
Serial.println(“initialization done.”);

//Сгенерируем имя файла
generateFileName();
myFile = SD.open(filename, O_WRITE | O_CREAT);

//Включаем протокол Wire
Wire.begin();
TWBR = 24;
Serial.println(“Initializing I2C devices…”);
//инициализируем акселерометр с гироскопом
accelgyro.initialize();
accelgyro.setMasterClockSpeed(13);
accelgyro.setI2CMasterModeEnabled(true);
//инициализируем компас
compass = HMC5883L();
setupHMC5883L();

//проверяем содеинение
Serial.println(“Testing device connections…”);
Serial.println(accelgyro.testConnection() ? “MPU6050 connection successful” : “MPU6050 connection failed”);

//калибруем датчик давления
pressure_m.bmp085Calibration();
}

void loop()
{
millis_t = millis();
//Считаем температуру (её знает датчик давления)
float temperature = pressure_m.bmp085GetTemperature(); //MUST be called first
//Считаем давление
float pressure = pressure_m.bmp085GetPressure();
//Вычислим высоту над уровнем моря
float altitude = pressure_m.calcAltitude(pressure);
float altitude_b = altitude – base_altitude;

//Проведём вычисления для скользящего среднего по высоте
run_alt[run_alt_index] = altitude_b;
//run_alt_summ = altitude_b;
if (run_alt_count == RUN_ALT_NUM)
{
last_run_alt_index = (run_alt_index == 0) ? RUN_ALT_NUM – 1 : run_alt_index – 1;
//run_alt_summ -= run_alt[last_run_alt_index];
}
else
{
run_alt_count =1;
}
run_alt_index = (run_alt_index 1 == RUN_ALT_NUM) ? 0 : run_alt_index 1;

//Временно вычисляем медленным методом
run_alt_summ = debug_get_alt_summ();

float run_altitude = run_alt_summ / (float) run_alt_count;

//Вычислим dt (интервал между замерами в миллисекундах)
if (t0 < 0)
{
t0 = millis_t;
}
else
{
dt = millis_t – t0;
t0 = millis_t;
}

if (run_altitude > max_altitude)
{
max_altitude = run_altitude;
}

if (millis_t – io_t > io_dt)
{
io_t = millis_t;
if (digitalRead(RESET_ALT_PIN) == HIGH)
{
reset_alt(altitude);
}

if (!is_done)
{
if (!is_fired)
{
if (is_prepared)
{
if (!is_armed)
{
if (max_altitude > arming_altitude)
{
is_armed = TRUE;
}
}
else
{
if (max_altitude – run_altitude > fire_minus_altitude)
{
is_armed = FALSE;
is_fired = TRUE;
fired_millis_t = millis_t;
}
}
}
}
else
{
if (millis_t – fired_millis_t > FIRE_TIME)
{
is_fired = FALSE;
is_done = TRUE;
is_prepared = FALSE;
}
}
}

if (is_armed != is_led_armed)
{
is_led_armed = is_armed;
digitalWrite(ARMED_PIN, is_armed ? HIGH : LOW);
}

if (is_fired != is_led_fired)
{
is_led_fired = is_fired;
digitalWrite(EXEC_PIN, is_fired ? HIGH : LOW);
}

}

//Интервал между замерами
Serial.print(“dt:”); Serial.print(dt / 1000, 3);
myFile.print(“dt:”); myFile.print(dt / 1000, 3);
//Сколько времени прошло с запуска?
Serial.print(” tm:”); Serial.print(millis_t);
myFile.print(” tm:”); myFile.print(millis_t);
//Температура, в градусах цельсия
Serial.print(” t:”); Serial.print(temperature, 2);
myFile.print(” t:”); myFile.print(temperature, 2);
//Давление, в паскалях
Serial.print(” p:”); Serial.print(pressure, 0);
myFile.print(” p:”); myFile.print(pressure, 0);
//Высота над уровнем моря, в метрах
Serial.print(” alt:”); Serial.print(altitude, 2);
myFile.print(” alt:”); myFile.print(altitude, 2);
//Высота над базовым уровнем, в метрах
Serial.print(” altb:”); Serial.print(altitude_b, 2);
myFile.print(” altb:”); myFile.print(altitude_b, 2);
//Высота над базовым уровнем, в метрах, скользящее среднее
Serial.print(” altr:”); Serial.print(run_altitude, 2);
myFile.print(” altr:”); myFile.print(run_altitude, 2);
//Высота над базовым уровнем, в метрах, максимальная
Serial.print(” Malt:”); Serial.print(max_altitude, 2);
myFile.print(” Malt:”); myFile.print(max_altitude, 2);

//Статусы:
Serial.print(” P”); Serial.print(is_prepared ? “1” : “0”);
myFile.print(” P”); myFile.print(is_prepared ? “1” : “0”);
Serial.print(” A”); Serial.print(is_armed ? “1” : “0”);
myFile.print(” A”); myFile.print(is_armed ? “1” : “0”);
Serial.print(” F”); Serial.print(is_fired ? “1” : “0”);
myFile.print(” F”); myFile.print(is_fired ? “1” : “0”);
Serial.print(” D”); Serial.print(is_done ? “1” : “0”);
myFile.print(” D”); myFile.print(is_done ? “1” : “0”);

//Считаем значения с магнитометра
MagnetometerScaled scaled = compass.ReadScaledAxis();
//Считаем значения с акселерометра и гироскопа
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

//Данные акселерометра:
Serial.print(” ax:”); Serial.print(ax);
Serial.print(” ay:”); Serial.print(ay);
Serial.print(” az:”); Serial.print(az);
myFile.print(” ax:”); myFile.print(ax);
myFile.print(” ay:”); myFile.print(ay);
myFile.print(” az:”); myFile.print(az);
//Данные гироскопа
Serial.print(” wx:”); Serial.print(gx);
Serial.print(” wy:”); Serial.print(gy);
Serial.print(” wz:”); Serial.print(gz);
myFile.print(” wx:”); myFile.print(gx);
myFile.print(” wy:”); myFile.print(gy);
myFile.print(” wz:”); myFile.print(gz);
//Данные магнитометра
Serial.print(” cx:”); Serial.print(scaled.XAxis, 3);
Serial.print(” cy:”); Serial.print(scaled.YAxis, 3);
Serial.print(” cz:”); Serial.print(scaled.ZAxis, 3);
Serial.println();
myFile.print(” cx:”); myFile.print(scaled.XAxis, 3);
myFile.print(” cy:”); myFile.print(scaled.YAxis, 3);
myFile.print(” cz:”); myFile.print(scaled.ZAxis, 3);
myFile.println();

myFile.flush();
}

//Настройка модуля HMC5883L (компаса)
void setupHMC5883L(){
//Setup the HMC5883L, and check for errors
int error;
error = compass.SetScale(1.3); //Set the scale of the compass.
if(error != 0) Serial.println(compass.GetErrorText(error)); //check if there is an error, and print if so

error = compass.SetMeasurementMode(Measurement_Continuous); // Set the measurement mode to Continuous
if(error != 0) Serial.println(compass.GetErrorText(error)); //check if there is an error, and print if so
}

/**
* Сброс высоты и перевод в состояние готовности – выполняется по нажатию кнопки
*/
void reset_alt(float current_alt)
{
base_altitude = current_alt;
is_prepared = TRUE;
is_armed = FALSE;
max_altitude = 0;
reset_running_alt();
}

/**
* Сброс скользящего среднего для высоты
*/
void reset_running_alt()
{
run_alt_index = 0;
run_alt_count = 0;
run_alt_summ = 0;
last_run_alt_index = 0;
for (int i =0; i<RUN_ALT_NUM; i )
{
run_alt[i]=0;
}
}

Данные, выдаваемые программой, должны быть примерно такими:

dt:0.048 tm:5760.00 t:26.80 p:100898 alt:35.61 altb:35.61 altr:35.60 Malt:35.60 P0 A0 F0 D0 ax:-1084 ay:16 az:-15708 wx:-282 wy:66 wz:-68 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:5807.00 t:26.80 p:100898 alt:35.61 altb:35.61 altr:35.61 Malt:35.61 P0 A0 F0 D0 ax:-1132 ay:100 az:-16276 wx:-282 wy:213 wz:-81 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.048 tm:5855.00 t:26.80 p:100898 alt:35.61 altb:35.61 altr:35.63 Malt:35.63 P0 A0 F0 D0 ax:-1016 ay:16 az:-15740 wx:-279 wy:149 wz:-78 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:5902.00 t:26.80 p:100895 alt:35.86 altb:35.86 altr:35.66 Malt:35.66 P0 A0 F0 D0 ax:-1152 ay:-48 az:-15596 wx:-247 wy:60 wz:-60 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:5949.00 t:26.80 p:100904 alt:35.11 altb:35.11 altr:35.64 Malt:35.66 P0 A0 F0 D0 ax:-1080 ay:-52 az:-15704 wx:-276 wy:54 wz:-61 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:5996.00 t:26.80 p:100902 alt:35.27 altb:35.27 altr:35.62 Malt:35.66 P0 A0 F0 D0 ax:-1152 ay:-44 az:-15652 wx:-290 wy:69 wz:-79 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:6043.00 t:26.80 p:100900 alt:35.44 altb:35.44 altr:35.60 Malt:35.66 P0 A0 F0 D0 ax:-1128 ay:-8 az:-15496 wx:-281 wy:37 wz:-70 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:6090.00 t:26.80 p:100897 alt:35.69 altb:35.69 altr:35.60 Malt:35.66 P0 A0 F0 D0 ax:-1048 ay:24 az:-15620 wx:-280 wy:59 wz:-75 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:6137.00 t:26.80 p:100902 alt:35.27 altb:35.27 altr:35.55 Malt:35.66 P0 A0 F0 D0 ax:-1164 ay:0 az:-15736 wx:-292 wy:73 wz:-69 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:6184.00 t:26.80 p:100899 alt:35.52 altb:35.52 altr:35.56 Malt:35.66 P0 A0 F0 D0 ax:-1088 ay:204 az:-15404 wx:-296 wy:-9 wz:-38 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.048 tm:6232.00 t:26.80 p:100897 alt:35.69 altb:35.69 altr:35.57 Malt:35.66 P0 A0 F0 D0 ax:-1220 ay:-340 az:-15976 wx:-261 wy:32 wz:-106 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.048 tm:6280.00 t:26.80 p:100902 alt:35.27 altb:35.27 altr:35.59 Malt:35.66 P0 A0 F0 D0 ax:-880 ay:144 az:-15828 wx:-289 wy:120 wz:-76 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:6327.00 t:26.80 p:100906 alt:34.94 altb:34.94 altr:35.53 Malt:35.66 P0 A0 F0 D0 ax:-1300 ay:52 az:-15292 wx:-274 wy:97 wz:-71 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:6374.00 t:26.80 p:100903 alt:35.19 altb:35.19 altr:35.50 Malt:35.66 P0 A0 F0 D0 ax:-1072 ay:-76 az:-15452 wx:-264 wy:55 wz:-74 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:6421.00 t:26.80 p:100905 alt:35.02 altb:35.02 altr:35.44 Malt:35.66 P0 A0 F0 D0 ax:-1040 ay:-4 az:-15844 wx:-297 wy:70 wz:-80 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:6468.00 t:26.80 p:100901 alt:35.36 altb:35.36 altr:35.40 Malt:35.66 P0 A0 F0 D0 ax:-1108 ay:64 az:-15644 wx:-294 wy:88 wz:-65 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:6515.00 t:26.80 p:100901 alt:35.36 altb:35.36 altr:35.39 Malt:35.66 P0 A0 F0 D0 ax:-1136 ay:80 az:-15628 wx:-287 wy:75 wz:-62 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:6562.00 t:26.80 p:100903 alt:35.19 altb:35.19 altr:35.36 Malt:35.66 P0 A0 F0 D0 ax:-1120 ay:-136 az:-15608 wx:-256 wy:37 wz:-76 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.047 tm:6609.00 t:26.80 p:100895 alt:35.86 altb:35.86 altr:35.38 Malt:35.66 P0 A0 F0 D0 ax:-1032 ay:-8 az:-15600 wx:-283 wy:81 wz:-68 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.048 tm:6657.00 t:26.80 p:100900 alt:35.44 altb:35.44 altr:35.35 Malt:35.66 P0 A0 F0 D0 ax:-1112 ay:-16 az:-15612 wx:-283 wy:59 wz:-77 cx:24508.800 cy:7121.720 cz:3551.200
dt:0.048 tm:6705.00 t:26.80 p:100901 alt:35.36 altb:35.36 altr:35.37 Malt:35.66 P0 A0 F0 D0 ax:-1084 ay:64 az:-15624 wx:-282 wy:73 wz:-66 cx:24508.800 cy:7121.720 cz:3551.200

Что означают данные:dt — интервал времени в миллисекундах с прошлого замераtm — количество миллисекунд, прошедшее с включения устройстваt — температура воздухаp — давление воздухаalt — высота по данным датчика-высотомераaltb — высота за вычетом «базовой» высоты, полученной при нажатии кнопкиaltr — скользящее среднее по последним 16 замерам высота altbЗначения-флаги (могут принимать значение 0 или 1, что означает НЕТ и ДА)

P — Была ли нажата кнопка установки базовой высоты, т.е. подготовлено ли устройство? (Prepared)A — Взведено ли устройство? Т.е. пройдена ли точка минимальной необходимой для взвода высоты (10 метров) (Armed)F — Активировано ли реле? т.е. выполнено ли условие снижения не 1 метр относительно максимальной набранной высоты?

(Fired)D — Закончена ли работа устройства? Этот флаг включается, когда выключается флаг F. После этого устройство больше никаких функций выполнять не будет, и для работы с ним его потребуется либо перезагрузить либо выключить и включить снова.

https://www.youtube.com/watch?v=s873edJaZpg

При этом те же самые данные программа будет писать на SD-карту, вставленную в кардридер. При каждом запуске устройства будет создаваться новый файл со следующим порядковым номером.

Смотрите про коптеры:  Простейший робот на одной микросхеме | Электронные игрушки | Схемы
Оцените статью
Радиокоптер.ру
Добавить комментарий