Bookmarks
Произвел обновление своего полетного хозяйства, а именно ретрансляторов радиоуправления и видео. Сейчас всё это выглядит так. Ретранслятор видео, внешний вид, интерфейс:
Функционал:
- Выбор рабочего канала из списка
- Выбор приемника (1-й, 2-й или диверсити режим)
- Выбор частоты и мощности передатчика 5.8 ггц
- Управление встроенным рекордером
- Автовыключение фпв экрана и тачскрина после начала записи
- Воспроизведение сделанных записей
- Управление всеми режимами ретранслятора с брелка 433 мгц (например, включение записи) (1 клик, долгое нажатие, двойной клик - и так по каждому каналу)
Если потребуется еще какой-то функционал, легко реализовать в коде. Из более менее дорогих комплектующих только дисплей Nextion. В остальном 5" экран с али, писалка Eachine, передатчик АКК, приемные модули 1.2, ардуина и разная рассыпуха.
Брелок:
Ретранслятор РУ:
Функционал:
- Два диапазона 433 мгц и 868 мгц (на базе QLRS)
- Индикация напряжения питания и потребляемого тока
- Отображение принятой телеметрии на встроенном экране
- Сохранение последнего принятого пакета с координатами GPS в энергонезависимую память (что удобно при поиске аппарата)
В дальнейшем планирую реализовать меню с настройками QLRS. Выбор частот, мощности для лоу, миддл и хай уровней, и т.д.
Как-то так. На подходе летающий ретранслятор LoRa 868 -> 2.4 и 1.2 -> 5.8 на базе 700 мм коптера, управление которым и удаленным фпв носителем осуществляется с одного пульта одновременно)) Летающий ретранслятор облетан и испытан на дальностях порядка 2-3 км (и сверхнизких высотах) до удаленного фпв носителя (450-й квадрик). Видео тестового полета выложу в ближайшее время.
Нужно всё это для реализации моей фетиш-идеи в виде полета на квадрике на 20-40 км и обратно на сверхмалой высоте, до 10-15 метров, что должно сделать лонг рэндж полеты в разы интереснее. Смотреть на Земплю в режиме гугл-мапс надоело, если честно 😃
<<То есть даже с частотой промахивается? Просто интересно если из передатчика, зарядки от мобилы и пластиковой бутылки можно было сделать SWR метр который не просто произвольные линии рисует, а помогает хотя бы сделать выбор между двумя антеннами, то может самому попробовать такой собрать.>>
На 5-6 ГГц самому собрать дома что то измерительное без других измерительных приборов задача нереальная. Вы не будите знать, валидный или невалидный результат показывает прибор. А так да, можно собрать мост на паре резисторов (или полосковых линий), пиндиода и тестера. OWLRC посмотрите на ютубе есть честные обзоры про него(
), в целом это просто потраченные деньги.
OWLRC - это скалярный анализатор (точнее только КСВ метр) на основе видео передатчика, не очень хорошего моста и детектора на обычных диодах сигнал с которых цифруется обычной атмегой, все максимально дешево и примитивно. Значения КСВ с OWLRC и норм. приборов не особо согласуются.
Arinst VR -это векторный анализатор минимального начального уровня с достаточно широкими возможностями, он тоже подвирает (если знать где смотреть) относительно профессионального оборудования, но терпимо. Настроить на нем антенну или согласовать линию на 5-6 ГГц вполне можно.
В дневнике у меня есть примеры по замерам большого количества антенн на 5.8.
<<На алике communication shop это не они, не знаете?>>
Да, они представлены на али. Смысл покупать из Воронежа через Китай ? Они CDEK отправляют без проблем.
По согласованию с Александром baychi предлагаю продолжить тут обсуждение его замечательной прошивки.
Baychi OpenLRS - открытый проект ПО совместимого с широким модельным рядом современного “железа” .
Базируется на исходных текстах Open LRS, KHA и исследованиях Александром baichy протокола Expert LRS.
Исходники находятся здесь - github!
Прошивка для передатчиков - Дневник.
Прошивка для приемников - Дневник.
Альтернативное руководство пользователя - Дневник.
Обзор железа для прошивки Baychi OpenLRS - Дневник.
Некоторая возможность обойти ограничение по редактированию первого поста, путем размещенных тут ссылок на дневники, в которых будут публиковаться последние изменения, что несколько облегчит задачу перелопачивания всей ветки.
Дружелюбной ЛРС я назвал потому, что позиция автора очень дружелюбна и открыта для предложений пользователей, что очень радует! 😃
Убедительная просьба, не обсуждать тут другие прошивки для ОпенЛРС, не умничать и не писать бессмысленные слова - “не реклама”!
Имеются в виду малогабаритные керамические фильтры от TaoGlas 433 868 915 www.taoglas.com/filters/ ? Они и два ватта вполне держат, в них все хорошо кроме потерь, а они порядка 2.6-2.9 дБ. Но все равно получается выигрыш если они давят помеху, которая душит приемник.
Мощный керамический фильтр огромный, он не влезет ни на один модуль. Не морочтесь потерями от фильтра+\- 2-3 дБ это не делает погоды. Чувствительность по паспорту у SX чипа около -120 дБ, эфирный шум на 868Мгц около -100 дБ, передатчик 1.2Г душит приемник SX модуля до падения чувствительности на уровень -85/-87дБ, 15 дБ про…, а ловим какие то 1-3 дБ. Керамику можете ставить и радоваться она и на вход и на выход работает. И сам приемник должен быть в экране нормальном,а не фольгой обкручен, тогда работа фильтра будет актуальной.
Довольно провокационный заголовок, не находите? Однако ниже я попробую показать, что реальное положение дел именно таково, поскольку подтверждается измерениями. Краткая предыстория вопроса. С начала сезона для дальних полетов я плотно использовал QCZEK LRS, сначала на 433, потом на 868 мгц. На 868 перешел потому, что размеры антенн оказались намного меньше, что особенно удобно на коптерах, где места прямо скажем немного, и приходится конкретно поломать голову, чтобы разместить все компоненты 😃 Антенны на обоих концах линка использовал Vee - диполи, настроенные точно по прибору на середину рабочего диапазона. Выходная мощность передатчика РУ чаще всего была около 250 мвт, иногда ее приходилось поднимать до 400, но в большинстве случаев до отметки 15 км на 250 мвт долетал или вообще без фейлсейфов, или буквально с одним фейлсейфом на одном и том же удалении, примерно на половине макс. дальности. При этом Лора модем, расположенный на коптере (приемник РУ и передатчик телеметрии на землю) вещал на мощности всего лишь 60-75 мвт, и в течение всего полета телеметрия на земле принималась вообще без каких-либо проблем. Т.е всегда, постоянно, без перерывов. И вот это несоответствие не давало мне покоя. Стало ясно, что проблема кроется где-то в радиочастотной совместимости оборудования, установленного на коптере. Сегодня до этого наконец дошли руки, и я решил провести ряд экспериментов, тем более, что Криштоф (автор QCZEK) выпустил обновление прошивки 1.92, в котором по моим баг-репортам он исправил вычисления RSSI в дбм и SNR (соотношение сигнал-шум) в дб. Видеть эти два параметра на земле мне было крайне необходимо, поскольку они позволяют моментально выяснить причину проблем с линком. И я ее выяснил, проведя 3 эксперимента.
Эксперимент первый. Выяснение пределов линка РУ в идеальных условиях.
Идеальные условия - это практическое отсутствие шумов в месте приема, не считая местного фона, теплового и т.д. Достиг я этого, установив 50 ом терминатор на входе приемника, а с ретранслятором РУ (с установленным Vee диполем) в одной руке и аппой в другой стал постепенно отходить от коптера. Места в доме не хватило, пришлось спуститься в подвал, чтобы добиться пропадания линка и фейлсейфа))
Результат: телеметрия показала, что фейлсейф случился при RSSI на уровне -116…-118 дбм и соотношении сигнал/шум на уровне -7 дб. Отрицательное с/ш - в порядке вещей, поскольку LoRa умеет “выковыривать” сигнал из-под уровня шумов в силу особенностей протокола. Для того, чтобы понимать, насколько это низкий уровень уровень сигнала, приведу такой пример. Пару лет назад, когда я летал на старой ЛРСке (EzUHF) yа расстоянии 20 км на 433 мгц при выходной мощности 200 мвт и передающей антенне (яги) с усилением 8 дб уровень принимаемого сигнала был около -90 дбм. Скидываем 5 дбм, представив, что поставили диполь вместо яги. Итого -95. Теперь такие расчеты. На 40 км получилось бы -101 дбм. На 80 км -107 дбм. На 160 км = -111 дбм. А ФС у лоры наступает при -118, как мы видели в домашнем рэндж тесте. Итого уже 320 км рисуется в конфигурации диполь-диполь 😃 С учетом влияния атмосферы и прочих шумов будет конечно поменьше, но расстояния получаются гигантскими, не правда ли? И они не выглядят прям уж фантастическими, потому что один радиолюбитель из Швейцарии добился 200 км дальности с лора модемами. В ютюбе есть ролик, кто хочет, может поискать.
Ок, это то, что мы можем получить в идеале. Теперь проводим
Второй эксперимент с выяснением пределов линка РУ в реальных условиях
Для этого на приемник на коптере ставим диполь, а терминатор ставим на передатчик ретранслятора РУ. Таким образом приемник будет собирать всю бортовую “гадость”, все помехи, а главное - начнет принимать мощный сигнал передатчика видео, антенна которого расположена буквально в 20 см. (на коптерах 450 размера места не особо много, да!) Снова гуляем по дому и спускаемся в подвал.
Результат: на этот раз фейлсейф поймался при уровне всего -87…-89 дбм при с/ш -7. Т.е реально уровень шума на входе приемника был в тот момент аж на уровне -81 дбм! Это очень много. В переводе на язык расстояний это означает, что 7-10 км будет вашим пределом по дальности, дальше пропадет радиоуправление. И это на лоре, с ее возможностью уходить ниже уровня шумов! На обычных лрсках, работающих в FSK, дальность оказалась бы более чем в 2 раза меньше. Всё это говорит нам только о том, что приемник лоры нехило задавлен близкорасположенным передатчиком видео на 1.2 ггц. Ок, подумал я, проведем еще один опыт, на этот раз с отключенным передатчиком видео. И что же вы думаете? На этот раз фейлсейф случился уже при -97…-99 дбм при с/ш -8. Если бы коптер был дальше от компа, то разница была бы еще больше.
Третий эксперимент. Раз есть помеха, от нее надо избавляться. Поэтому сделал по-быстрому режекторный фильтр на частоту моего передатчика видео 1160 мгц. Настраивал его по прибору, подавление на частоте 1160 мгц оказалось порядка 30 дб. Чуть даже промазал, мог бы 35 дб получить в идеале. Через тройничок прикрутил его ко входу приемника и пошел делать измерения. И снова, что и требовалось доказать: на этот раз фейлсейфы начались при уровне сигнала -101…-103 дбм при с/ш -8 дб. Решил перепроверить, снял фильтр. Получил прежний результат: фейлсейфы пошли при уровне -87…-89 дбм при с/ш -7.
А это, на секундочку, целых 14 дб разницы, или порядка 6 раз по дальности. Учитывая, что на 250-400 мвт я спокойно долетал на 15 км на диполях на обоих концах линка, прогнозируемая дальность его работы оказывается порядка 90 км, что более чем достаточно. В общем, на этом вопрос с ограниченной дальностью РУ линка на лоре (да и на других лрс тоже) можно считать закрытым. Учитывая все вводные, полагаю, что я исследовал его исчерпывающе. Конечно, остается еще окончательно проверить выводы в реальном полете, но 90% вероятности, что именно так всё и окажется. Какие-то погрешности могут появиться из-за влияния атмосферы или помеховой обстановки в зоне полета, но не думаю, что это влияние будет критичным.
Теперь окончательный вывод. Я утверждаю, что 90% проблем с ограниченной дальностью работы систем дальнего радиоуправления моделями (ЛРС, LRS) происходят из-за “оглушения” приемника радиоуправления близкорасположенным передатчиком видео. Дополнительный вклад вносят шумы от других компонентов: пишущей или ФПВ камеры (они очень фонят на 433 мгц), полетного контроллера и т.д. Столкнувшись с маленькой дальностью недешевых и казалось бы отличных систем ЛРС, летчики-пилоты обычно начинают “шаманить” с антеннами, с попытками поднять мощность передатчика и т.д. Это всё мертвому припарки и ловля блох. Потому что даже антенна с КСВ равным 3 (т.е ппц как расстроенная) на рабочей частоте теряет (или “недособирает” скорее) лишь около 10% ЭМ энергии, а это сущие копейки для бюджета линка!
Далее, мощность передатчика. 250 мвт - это 24 дбм. 1 Вт - 30 дбм. А теперь вдумайтесь в следующее: это всего лишь 6 дб разницы или 2 раза по дальности! ВСЕГО ЛИШЬ. А из-за “оглушения” приемника РУ передатчиком видео мы теряем порядка 14 дб (102-88 = 14 дб, см. данные моих измерений) а 14 дб, это порядка 6 раз по дальности. Без забития приемника РУ мощным сигналом с передатчика видео, дальность работы радиоуправления была бы в 6 раз больше! Т.е мы видим, что поднимать мощность передатчика - тоже не выход. Эффект очень слабый. Сильный эффект, будет, кстати говоря, если вместо диполя на передатчик поставить хорошую направленную антенну, яги или Харченко. Последняя мне спокойно дает 10 дб прироста, что решило бы все мои проблемы с линком. Но я не сторонник забивания гвоздей микроскопом! 😃 Всегда лучше решить проблемы на стороне приемника, чем увеличивать мощность передатчика. Ни к чему вносить свой вклад в глобальное потепление 😃 да и эээ… balls поберечь бы надо, пригодятся. А это, кстати, камень в сторону отдельных ЛРС с выходной мощностью в 7 ватт 😃 Для сравнения: телеметрия с лора модема принималась с расстояния 18 км при мощности 75 мвт без единого затыка. Вот тут “кто-то” слетал и протестировал))
В общем, если перейти от теории к практике, то гарантированным решением большинства проблем с ограниченной дальностью РУ линка (особенно если входные каскады приемников не блещут хорошей схемотехникой, что справедливо для очень, очень многих систем ЛРС) является режекторный фильтр точно на частоту вашего передатчика видео, подключенный между антенной приемника и входом приемника РУ. Этот фильтр решает проблему “оглушения” (забития, низкой избирательности по соседнему каналу) приемника РУ, хотя и вносит небольшие потери в уровень принимаемого сигнала. Тем не менее, от него в 100 раз больше пользы, чем вреда, что мы и видели на конкретных цифрах.
Если будет время, попробую снять видео, где подробно покажу процедуру измерений. Всегда лучше один раз увидеть, что сто раз прочитать 😃
update. Как показали дальнейшие опыты, режекторный фильтр на частоту передатчика видео проблему решает не полностью. Коллеги по хобби подсказали, что гораздо лучше на входе приемника применять полосовой фильтр, оставляющий из всего спектра принимаемых антенной частот только те, что составляют рабочую полосу приемника, и отсекающий все те, что лежат вне этой полосы. Рабочая полоса в нашем случае - 868-870 мгц. Режекторный фильтр можно использовать, если не нужна передача телеметрии с борта, т.к применение такого фильтра поднимает КСВ система антенна-фильтр вплоть до 7, что уже неприемлемо (хотя при малых мощностях, 50-100 мвт - некритично). Полосовой фильтр на ПАВ (SAW) таким недостатком не обладает. КСВ с ним не более 1.8 в рабочей полосе частот.
Такой фильтр я в итоге изготовил самостоятельно. Характеристики получились следующими:
- Вносимое затухание в полосе 868-870 мгц: 2.4…2.6 дб
- Подавление частот вне рабочей полосы: не хуже 45 дб
- Подавление частот передатчиков видео 1160-1280 мгц: порядка 50 дб
- КСВ в рабочей полосе частот: 1.6-1.8
- Вес: 4 грамма
Выглядит он так:
Скриншоты амплитудно-частотных характеристик:
На этом могу констатировать, что проблема с ограниченной дальностью системы РУ QCZEK LRS (и аналогичных) решена. 😃
Запилил беспроводной симулятор из переходника USB - NRF24L01.
Вставляется в USB и конектится без провода к ардуиновскому передатчику из предыдущего поста.
В итоге имеем 8 каналов: 6 осей и 2 выключателя, что позволяет запускать HELI-X на большом экране и не бегать к компу нажимать пробел чтобы запустить двигатель.
Драйверов для него не требуется, автоматом опознается как джойстик в Windows и Ubuntu.
Прошивка Arduino_8ch_Joystick.hex на гите.
Прошивка для аппы FlySky на подходе, другие по запросу.
Ну и видео как оно в работе)
Простой и бюджетный DIY передатчик с поддержкой модульных приемников серии Rainbow RX.
Все собиралось в корпусе от 40 мегагерцового передатчика пилотажной Стрекозы.
У него довольно качественные стики и самое главное - в отсек для батареек влазит пятивольтовый Power Bank на одной батарейке 18650.
Микроконтроллер использован Atmega8: задействованы 6 аналоговых входов для осей и 2 цифровых для переключателей.
Радиомодуль NRF24L01 с усилителем, экраном и SMA антенной.
Питание 5V от Power Bank через выключатель подается на AMS1117, с нее 3.3V питают всю остальную схему.
Atmega опрашивает стики и выключатели, пакует по байтам для библиотеки Rf24 и отправляет в эфир.
Потребление всего хозяйства 50мА, что дает при емкости Power Bank 2600мАч теоретически около 50 часов полетов или игры в симуляторе.
Скетч для Arduino и прошивка Rainbow RX с поддержкой передатчика на гите.
Привет!
По просьбам телезрителей переделал механику под slip-ring 22мм. Установка его по-желанию, так что, кто желает работать с сервами 180-180 с перекидыванием головы тоже без проблем могут использовать, пропустив сквозь отверстие провода. Архив с исходниками солида тут
Опять-таки, интересуются подробностями по механике, поэтому добавил небольшую инструкцию по механической части и другим покупным деталям -> PartsList_RUS. Вроде все доступно, ну и со ссылками. Выглядит примерно так
Если кому нужны STL для печати, то есть на thingiverse
Доделал oled-дисплейчик для наземной станции, разобрался какие пакеты приходят от qczek, что можно использовать. Координаты дома, похоже, не приходят (
Поэтому как вариант для постройки трекера в будущем - брать первые “хорошие” координаты, ставя коптер возле ретранслятора. Ну, придет время - буду пробовать.
Отображаются построчно:
- GPS координаты в degree, как в конфигураторе, все совпадает
- Число спутников, фикс, загрузка процессора (у меня всегда 0 почему то) и число ошибок UART, I2C, SPI, CAN (dropped packets on all links (packets that were corrupted on reception on the MAV))
- Курс по компасу, скорость по gps, высота по баро
- потребление в амперах, напряжение батареи, процент оставшегося “топлива” по мнению контроллера.
В принципе, данных для отображения еще валом, но я взял за 70руб на пандао экранчик i2c 128x32, лучше бы 128x64 конечно взять.
Используются библиотеки mavlink и SSD1306Ascii.
Ардуинка 328я (нано в моем случае). При отсутствии данных 5 секунд и “хороших” значениях lat, lon, fix_type производится запись оных в еепром и отображение на экране. Если ребутнуть ардуину, то пока mavlink не появится, будут отображаться эти данные, периодически сменяясь на 0.3 сек надписью “wait for mavlink”. Если связь восстановится, то покажутся актуальные данные. Запись в епром производится ТОЛЬКО при пропадании mavlink и нормальных последних данных. Мне кажется, этого достаточно. Ресурс еепром тоже не бесконечный.
Допиливать еще есть что, но уже можно повторять. Подключается просто: дисплей на i2c шину ардуинки (SDA<>A4 / SCL <> A5), выход TXD модуля qczek на RX ардуины (и заодно параллельно на блютус).
Скетч:
#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include <mavlink.h>
#include <EEPROM.h>
#define I2C_ADDRESS 0x3C
#define RST_PIN -1
SSD1306AsciiWire oled;
#define MAV_TIMEOUT 5000 //mavlink timeout
#define SERIAL_SPEED 9600 //9600 for sbus, 57600 for cppm
#define DEBUG
mavlink_message_t msg;
mavlink_status_t status;
//mavlink_global_position
int32_t alt, relative_alt;
int16_t vx, vy, vz;
uint16_t hdg;
//__mavlink_sys_status_t
int8_t battery_remaining;
uint16_t current_battery, voltage_battery, cpu_load, drop_rate_comm;
//mavlink_gps_raw_int_t
int32_t lat, lon, gps_alt;
uint8_t satellites_visible, fix_type;
uint16_t cog, vel;
//oth
uint8_t flag, eeprom_flag;
uint32_t time_flag;
//------------------------------------------------------------------------------
void setup() {
Wire.begin();
Wire.setClock(400000L);
oled.begin(&Adafruit128x32, I2C_ADDRESS);
display_wait();
//
Serial.begin(SERIAL_SPEED);
//
time_flag = millis();
}
//------------------------------------------------------------------------------
void loop() {
while(Serial.available()) {
uint8_t c= Serial.read();
if(mavlink_parse_char(MAVLINK_COMM_0, c, &msg, &status)) {
flag = 0;
switch(msg.msgid) {
case MAVLINK_MSG_ID_HEARTBEAT: {
break;
}
case MAVLINK_MSG_ID_GLOBAL_POSITION_INT: {
mavlink_global_position_int_t packet;
mavlink_msg_global_position_int_decode(&msg, &packet);
if(packet.hdg == 65535) packet.hdg = 0;
//if(lat != packet.lat) { lat = packet.lat; set_flag(); }
//if(lon != packet.lon) { lon = packet.lon; set_flag(); }
//if(alt != packet.alt) { alt = packet.alt; set_flag(); }
if(relative_alt != packet.relative_alt) { relative_alt = packet.relative_alt; set_flag(); }
//if(vx != packet.vx) { vx = packet.vx; set_flag(); }
//if(vy != packet.vy) { vy = packet.vy; set_flag(); }
//if(vz != packet.vz) { vz = packet.vz; set_flag(); }
if(hdg != packet.hdg) { hdg = packet.hdg; set_flag(); }
break;
}
case MAVLINK_MSG_ID_SYS_STATUS: {
__mavlink_sys_status_t packet;
mavlink_msg_sys_status_decode(&msg, &packet);
if(battery_remaining != packet.battery_remaining && packet.battery_remaining >= 0) { battery_remaining = packet.battery_remaining; set_flag(); }
if(voltage_battery != packet.voltage_battery && packet.voltage_battery != 65535) { voltage_battery = packet.voltage_battery; set_flag(); }
if(current_battery != packet.current_battery) { current_battery = packet.current_battery; set_flag(); }
if(cpu_load != packet.load) { cpu_load = packet.load; set_flag(); }
if(drop_rate_comm != packet.drop_rate_comm) { drop_rate_comm = packet.drop_rate_comm; set_flag(); }
break;
}
case MAVLINK_MSG_ID_ATTITUDE: {
break;
}
case MAVLINK_MSG_ID_GPS_GLOBAL_ORIGIN: {
break;
}
case MAVLINK_MSG_ID_RC_CHANNELS_RAW: {
break;
}
case MAVLINK_MSG_ID_VFR_HUD: {
break;
}
case MAVLINK_MSG_ID_GPS_RAW_INT: {
__mavlink_gps_raw_int_t packet;
mavlink_msg_gps_raw_int_decode(&msg, &packet);
if(packet.cog == 65535) packet.cog = 0;
if(packet.vel == 65535) packet.vel = 0;
if(packet.alt == 65535) packet.alt = 0;
if(lat != packet.lat) { lat = packet.lat; set_flag(); }
if(lon != packet.lon) { lon = packet.lon; set_flag(); }
//if(gps_alt != packet.alt) { gps_alt = packet.alt; set_flag(); }
if(vel != packet.vel) { vel = packet.vel; set_flag(); }
if(cog != packet.cog) { cog = packet.cog; set_flag(); }
if(fix_type != packet.fix_type) { fix_type = packet.fix_type; set_flag(); }
if(satellites_visible != packet.satellites_visible) { satellites_visible = packet.satellites_visible; set_flag(); }
break;
}
default: {
#ifdef DEBUG
Serial.println(msg.msgid); //see unused packet types
#endif
break;
}
}//switch
if(flag == 1) {
display_data();
}//print flag
else {
no_data();
}
}//if mavlink_parse_char
}//while serial available
no_data(); //check no serial input data fuction
}
void set_flag() {
flag = 1;
eeprom_flag = 0;
time_flag = millis();
}
void display_wait() {
oled.setFont(font8x8);
oled.set2X();
oled.clear();
oled.println("WAIT FOR");
oled.println("MAVLINK");
oled.set1X();
oled.setFont(font5x7);
}
void display_data() {
oled.clear();
printL(lat); //gps
oled.print(" ");
printL(lon);
oled.println();
oled.println((String)"SA:"+satellites_visible+(String)" F:"+fix_type+(String)"D L:"+cpu_load/10+(String)"% E:"+drop_rate_comm/100+(String)"%");
oled.println((String)"H:"+hdg+(String)" S:"+(uint8_t)(vel/100*3.6)+(String)"kmh A:"+relative_alt/1000+(String)"m");
oled.println(current_battery/100.0+(String)"A "+voltage_battery/1000.0+(String)"V R:"+battery_remaining+(String)"%");
}
void printL(int32_t degE7) {
// Extract and print negative sign
if (degE7 < 0) {
degE7 = -degE7;
oled.print( '-' );
}
// Whole degrees
int32_t deg = degE7 / 10000000L;
oled.print( deg );
oled.print( '.' );
// Get fractional degrees
degE7 -= deg*10000000L;
// Print leading zeroes, if needed
int32_t factor = 1000000L;
while ((degE7 < factor) && (factor > 1L)){
oled.print( '0' );
factor /= 10L;
}
// Print fractional degrees
oled.print( degE7 );
}
void no_data() {
if((millis() - time_flag) > MAV_TIMEOUT ) { //no mavlink data at 2sec
#ifdef DEBUG
Serial.println((String)"LOST MAVLINK DATA");
#endif
display_wait();
delay(300);
if(eeprom_flag == 0 && lat != 0 && lon != 0 && fix_type > 1) { //if gps coordinates present, save it
#ifdef DEBUG
Serial.println("save..");
#endif
EEPROM_int32_write(5, lat);
EEPROM_int32_write(16, lon);
EEPROM.write(30, satellites_visible);
EEPROM.write(32, fix_type);
EEPROM.write(34, cpu_load);
EEPROM.write(40, drop_rate_comm);
EEPROM.write(46, hdg);
EEPROM.write(52, vel);
EEPROM_int32_write(56, relative_alt);
EEPROM.write(66, current_battery);
EEPROM.write(72, voltage_battery);
EEPROM.write(74, battery_remaining);
eeprom_flag = 1;
} else { //no fresh data on mavlink, read from memory
#ifdef DEBUG
Serial.println("read..");
#endif
lat = EEPROM_int32_read(5);
lon = EEPROM_int32_read(16);
satellites_visible = EEPROM.read(30);
fix_type = EEPROM.read(32);
cpu_load = EEPROM.read(34);
drop_rate_comm = EEPROM.read(40);
hdg = EEPROM.read(46);
vel = EEPROM.read(52);
relative_alt = EEPROM_int32_read(56);
current_battery = EEPROM.read(66);
voltage_battery = EEPROM.read(72);
battery_remaining = EEPROM.read(74);
eeprom_flag = 1;
}
display_data();
time_flag = millis();
}
}
int32_t EEPROM_int32_read(int addr) // чтение из EEPROM 4 байта unsigned long
{
byte raw[4];
for(byte i = 0; i < 4; i++) raw[i] = EEPROM.read(addr+i);
int32_t &data = (int32_t&)raw;
return data;
}
//*****************************************************************
void EEPROM_int32_write(int addr, int32_t data) // запись в EEPROM 4 байта unsigned long
{
byte raw[4];
(int32_t&)raw = data;
for(byte i = 0; i < 4; i++) EEPROM.write(addr+i, raw[i]);
}