🏆 Рейтинг ІТ-роботодавців 2018: вже зібрано більше 13 000 анкет. Оціни свою компанію!
×Закрыть

DIY. Подводный дрон. История одного сумасшествия

В этом материале описано проектирование, разработка и сборка прототипа подводного дрона на базе Raspberry PI и управление им с Android-смартфона. Статья может пригодиться как новичкам (изложены азы управления электродвигателями, диодами, камерами, гироскопом), так и опытным инженерам (они могут поглумиться над исполнением и решениями :)). В общем, если вы любитель сделать чего-то электронного своими руками — милости прошу к прочтению.

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

После серфинга в интернете я нашел довольно много решений, но большинство из них либо еще не вышли в массы и находились в состоянии прототипов, либо стоили некисло дорого (3++к енотов). Если интересно, то можете глянуть пару хороших здесь.

Забегая наперед, скажу, что у меня вышел рабочий прототип, который способен плавать на нескольких метрах глубины, со всеми плюсами и минусами. Сложно сказать, что в результате я получил продукт, которым можно легко управлять и что он сейчас готов сделать что-то большее, чем унять инженерный азарт. Но все узлы у него работают исправно, и главное, что мои ошибки и наработки могут помочь кому-то сделать что-то значимое (даже если для только него самого).

Так как работы было проделано действительно много, можно разделить все по следующим темам:

В порядке бреда

Скажу сразу: я любитель, и большинство из того, что я делал, было сделано методом научного тыка, ибо собрать что-то и протестить на-а-амного веселее, чем просчитать и понять, что в теории оно не работает. Вариантов конструкции и идей было немалое количество, и были откровенно «глупые» реализации (одна из них будет описана чисто по приколу далее).

Первым и основным заданием было понять, каким образом можно сделать в бытовых условиях герметичный корпус и при этом передать момент на гребные винты.

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

На шестеренку было прикручено по два магнита и соединены с двигателями (соблюдая все полярности магнитов), между шестернями пластина которая имитирует стенки корпуса. Если у вас проснулось желание закрыть статью и выколоть себе глаза — это нормальная реакция на увиденное, но я вас предупреждал в начале :)

Несмотря на кривизну, после запуска макета можно смело прокричать: «И все-таки она вертится» ©. Момент передается, детали вращаются, но за счет притяжения сильно возрастает трение. Следующий минус, помимо десятков остальных, в том что если стопнуть воображаемый винт, то магниты теряют «контакт» и второй раз уже сцепиться не могут из-за разности скоростей.

Даже если собрать такую конструкцию, использовав подшипники, нормальные шестерни и магниты, это будет далеко не самым лучшим решением, ибо КПД, простота реализации и просто здравый смысл хромают.

В итоге принято решение не выпендриваться и взять бесколлекторный движок, и при надобности залить лаком обмотку. Вынести за корпус (да-да, в самую воду) и просто загерметизировать выведенные провода. Это будет значительно проще, чем думать конструкцию с маслом и сальниками или еще какой-то сложный механизм, для того, чтобы удержать воду вне механики и электроники.

Итак, перейдем к более серьезным вещам.

Выбор компонентов

Далее список того, что было использовано при создании аппарата.

Материнка

В качестве контроллера однозначно была выбрана «малинка» (Raspberry PI 3B). Arduino-подобные платы для такой комплексной задачи сразу отпали, так как надо контролировать минимум 4 двигателя, диоды, гироскоп, отправлять поток видео с камеры и при этом получать и обрабатывать команды с устройств управления.

Малина идет со встроенным Wi-Fi и Ethernet под RJ-45, что несомненно позволит произвести все эти операции.

Канал связи

Да, да — витая пара

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

  1. Возможность передачи под водой.
  2. Скорость такой передачи.
  3. Универсальность (не надо изобретать велосипед ни на распберри, ни на передатчике).

Есть специальный кабель для воды с нулевой плавучестью и прочими прелестями, но купить 100 метров отдельно нельзя, а тратить 500+ баксов на катушку я не захотел.

Передатчик «на суше»

Мини-роутер NEXX

Было 3 основных варианта передачи.

  1. Попробовать вывести проводом Wi-Fi антенну из воды на сушу (вместо витой пары кабель одножильный), но тут много было спорных моментов.
  2. Построить мост на двух Raspberry как клиент-сервер (было бы уместно, но дороже и геморней).
  3. Взять готовый мини-роутер и соединить витой парой с малиной. Этот вариант был взят за основу, так как он самый надежный, быстрый и дешевый. Как показала практика, это неплохой вариант.

Электродвигатель

N2830/2212 1000KV
После испытания 3 разных моторов выбор пал именно на эту модель. Почему? Да все просто — он достаточно мощный, у него есть вторая ось и можно повесить 2 винта. Все двигатели нормально работают в воде до первого попадания водорослей или песка. Если брать высокооборотистые и менее мощные — вода не их стихия. Более дешевые варианты тоже не оправдали надежд. В общем цена/качество.

Плата управления (ESC)

Afro ESC (30A)
Тоже довольно все просто. Ее можно запрограммировать на переключение forward/reverse, и мощности 30 ампер должно хватить на испытуемые моторы. Плюс ко всему, их не надо было ждать месяц-другой из Китая (но, конечно же, есть одно но:).

Afro ESC USB Программатор

Программатор для наших ESC. С помощью этого девайса можно залить нужную прошивку. Собственно говоря, это и есть «но». Ждать пришлось полтора месяца.

Светодиод

CREE XHP50
Эта модель способна выжигать все живое световым потоком. Такая цель и была.

Импульсный драйвер для светодиодов

7-30В 3А
Отлично подходит для наших целей — держит два вышеуказанных светодиода, а главное — подключается к малинке и позволяет плавно регулировать яркость диодов.

Гироскоп

MPU-6050
Трехосевой гироскоп/акселерометр, который будет отправлять данные на Raspberry о местоположении в пространстве. Сильно они не пригодились, но данные были :)

Камера

RPi Camera F
Или любая другая нативная камера Raspberry PI. Главное условие — чтобы она коннектилась через шлейф, а не была USB. С видеостримингом всегда были проблемы (задержки, кодинг), точнее, это не проблемы, а «надо убить много времени, чтобы завелось».

Джойстик

iPega PG-9055 — помощник управления, если у вас руки мокрые, а они такими будут, можно включить управление данным девайсом.

Батарея

Turnigy 2200mAh 3S 30C
Снова был ряд тестов и выбор. Батареи 18650 не подошли, ибо у контроллера ток разряда был 25А, чего не хватало всей системе на пиках (да, пару батарей умерло смертью храбрых после использования). Можно было попробовать соорудить на 6 батареях и получить 50А, но это сложнее. Кабелем такую мощность постоянного(!!) тока передать нереально (помним про дистанцию 100 м). Так что взял Li-Po, которая шикарно справилась со своей задачей и поместилась в корпус.

И остальное

Программирование ESC

К сожалению, Afro ESC из коробки имеет только одно направление вращения, поэтому надо «шить». Самая засада в том, что надо ждать линкер из Китая, остальное детали. Предположим, что он у вас уже есть :)

Совет, который я встретил на просторах интернета, — купить USB хаб, чтобы в случае короткого замыкания сгорел он, а не ваш дорогой ноут. Но каждый волен выбирать свою судьбу :)

Качаем файл прошивки на диск и программу для прошивки KKMulticopter Flashtool.

Теперь важно не натупить с подключением проводов, ибо последствия могут быть печальные для какого-то устройства. Краткий ликбез по ESC по проводам:

  1. Пара красный-черный толстых кабелей с бананом «папой» на конце. Силовое питание двигателя. Я подавал 12 вольт и ампер — сколько просило :)
    1. Красный — ВХОД плюс.
    2. Черный — ВХОД минус.
  2. Толстые провода красный-черный-желтый — питание на двигатель. Пока мы их не трогаем, но в дальнейшем будем соединять на аналогичные «цвета» электродвигателя.
  3. Тонкие провода управления и питания.
    1. Желтый — это непосредственно кабель, по которому передаем сигнал управления.
    2. Красный — выход 5в (в целом я его не использовал). Их есть несколько разных типов, если захотите — читайте.
    3. Черный — минус.

Подключаем тонкие провода к Linker’у: минус к минусу (черные) и сигнал на сигнал (желтые). Тонкий красный не трогаем и не подключаем. Далее даем питание на плату (черный и красный входы). Лично я использовал этот импульсный блок, но подойдет любой с похожими характеристиками.

Открываем программу прошивки и выбираем:

Programmer: Turnigy USB Linker or Afro USB Linker (зависит о того, что у вас есть).
Port: собственно тот USB, куда включили. Благо, выбор там не велик.
Baud rate: 9600.
Controller: atmega 8-based brushless ESC (8kB flash).

И выбираем уже скачанный файл прошивки. Жмем кнопку «Run» и молимся :) Скоро прошивка успешно зальется на ESC, и все будет готово. Весь процесс можете посмотреть здесь:

Из 8-ми программируемых мною ESC сдох только один :)

Настройка Raspberry PI сервера

Теперь перейдем к настройке Raspberry PI.

  1. Качаем последний дистрибутив системы тут.
  2. Скачиваем и устанавливаем Etcher.
  3. Вставляем пустую microSD флешку в картридер (тут уже сами думайте, где их взять).
  4. Открываем Etcher и выбираем zip или img Raspbian, который скачали на первом шаге.
  5. Нажимаем ’Flash!’
  6. Ждем окончания установки и извлекаем microSD.
  7. Вставляем флешку в наш Raspberry.

Для тестов нам будет достаточно «малинки», телефона на базе Android и любого Wi-Fi роутера с доступом к интернет. Если вы любитель консольного общения с устройствами, то вам ничего объяснять и не надо, сами справитесь. Для более ленивых — подключаем монитор, клавиатуру (HDMI и USB порты работают на «ура» из коробки), питание от какого-то USB-microUSB и грузим систему. Важно помнить, что на все двигатели подаем 12V, а на Raspberry — 5V. Также важно, если выключить резко питание на малину — может побиться операционная система (связано это с памятью самого устройства). Так что лучше подумать о бесперебойности.

Подключаем к сети Wi-Fi, и в целом система готова. Я бы советовал настроить ваш роутер и дать static IP адресс для малины, ибо подключаться будем именно по IP.

Если вы уже работали с Linux, то дальнейшие действия вам будут не дики. Самым простым способом создать серверное приложение будет NodeJS. Разобраться, что да как не составляет труда, так как в Гугле еще никого не банили. Открываем терминал и поехали:

sudo apt-get update
sudo apt-get dist-upgrade
sudo apt-get install -y nodejs

И проверочно запускаем node -v, дабы точно понять, что все установилось.

Можно сразу слить весь проект с репозитория и запустить (ссылка будет в конце статьи), но разве мы здесь ради этого собрались? :) Теперь создаем папку нашего проекта mkdir ~/drone и переходим в нее cd ~/drone и инициализируем проект: npm init. Установщик спросит название и индекс файл — укажем app.js.

После инициализации ставим express: npm install express. И создаем файл app.js: touch app.js.

Для тех, кто работает с GUI (моник и клава), советую поставить Atom. В нем очень даже удобно писать js-код. Для остальных — Vim, Nano, MCEdit (и сами знаете).

Далее добавляем код в app.js и сохраняем файл:

'use strict';
const express = require('express');
const net = require('net');
const app = express();

const server = net.createServer((socket) => {
  socket.on('data', (data) => {
    var command = data.toString();
  	console.log(err);
  });
}).on('error', (err) => {
  console.log(err);
  // handle errors here
  // throw err;
});
server.timeout = 0;
// grab an arbitrary unused port.
server.listen(49655, () => {
  console.log('opened server on', server.address());
});

И запускаем из консоли node app.js в папке(!!) drone. Теперь у вас крутится сервер, который слушает подключения на 49655 порт. Запомним: наш локальный IP (ifconfig в консоли) и все подключения будем производить на IP:49655.

Сейчас давайте усложнять конструкции :)

Управление электродвигателями с Raspberry PI

Итак, начинаем самую веселую часть нашей работы — пишем управление на Raspberry PI. Идем в папку проекта ~/drone и устанавливаем PiGpio библиотеку:

sudo apt-get update
sudo apt-get install pigpio
npm install pigpio

Теперь небольшой ликбез по управлению ESC. Нам надо передать некую частоту на управляемый провод (желтый тонкий) (см. раздел «Программирование ESC»). Прошивка afro_nfet_besc30_r1 имеет диапазон 1100-1900, где значение 1500 — состояние спокойствия, 1100 макс реверс, 1900 макс форвард.

Создаем файлик engines.js и в него добавляем JS-код:

//Константа состояния спокойствия
const SERVO_ZERO = 1500;
//Подключаем библиотеку 'pigpio'
const Gpio = require('pigpio').Gpio;

//Определяем наши 4 двигателя по пинам расбперри (пиновка будет объяснена чуть ниже)
const servo1 = new Gpio(22, {mode: Gpio.OUTPUT});
const servo2 = new Gpio(10, {mode: Gpio.OUTPUT});

const servo3 = new Gpio(9, {mode: Gpio.OUTPUT});
const servo4 = new Gpio(27, {mode: Gpio.OUTPUT});

//Устанавливаем каждой плате состояние “спокойствия”
servo1.servoWrite(SERVO_ZERO);
servo2.servoWrite(SERVO_ZERO);
servo3.servoWrite(SERVO_ZERO);
servo4.servoWrite(SERVO_ZERO);

//По вызову этого метода пишем значение в наш ESC
module.exports.engines = {
  leftEsc: (value) => {
    servo1.servoWrite(value);
  },
  rightEsc: (value) => {
    servo2.servoWrite(value);
  },
  topLeftEsc: (value) => {
    servo3.servoWrite(value);
  },
  topRightEsc: (value) => {
    servo4.servoWrite(value);
  }
}

Дабы использовать этот код, пишем в app.js:

const engines = require('./engines.js').engines;
engines.leftEsc(*VALUE[1100;1900]*);

Собственно говоря, servo1.servoWrite() — и есть магическое управление. Подаем 1100 — двигатель крутится в реверсном направлении. Подаем 1900 — max forward. А вот распиновка нашей малины:

Если вкратце, то мы используем оранжевые GPIO. Одна пара GPIO 10 — GPIO 22, вторая GPIO 9 и GPIO 27 (логичнее было бы использовать 27;22 10;9, но при пайке не учел, и пришлось поменять). Если брать по порядочным числам (указаны серым), то это 13;15 и 19;21 контакты. На каждый из них подключаем желтые провода из ESC, а минус же объединяем в один GND, к примеру 39 контакт.

Осталось подключить остальное. Коннектим провода питания (красный и черный) Afro ESC к отдельному блоку питания(12v), подключаем моторы к желтый-красный-черный толстым проводам и уже можем играться. Например, допилить код и по интервалу подавать разные сигналы на пины. Небольшое видео, правда, там управление осуществляется с Android, но это опишу немного позже:

Гироскоп

Подключаем:
VCC к пину 1 (3.3V PWR)
GND к любому минусу
SCL к пину 5 (GPIO 3)
SDA к пину 3 (GPIO 2)

Подключение не сложное, а программно еще проще — хорошие люди сделали все до нас. На помощь спешат библиотеки i2c-bus и i2c-mpu6050.

Устанавливаем в проект:

npm install i2c-bus
npm install i2c-mpu6050

Создаем файл gyroscope.js и добавляем:

const i2c = require('i2c-bus');
const MPU6050 = require('i2c-mpu6050');

const address = 0x68;
const i2c1 = i2c.openSync(1);
const sensor = new MPU6050(i2c1, address);

var reading = false;
var sensorData = {};

module.exports.gyroscope = {
  getData : () => {
    return JSON.stringify(sensorData);
  },
  readRotation : () => {
    sensor.readRotation(function (err, rot) {
      if (err) {
        console.log(e);
        return;
      }
      console.log(rot);
    });
  },
  readSensor : () => {
  	if (!reading) {
  		reading = true;
  	}
  	sensor.read(function (err, data) {
      reading = false;
  		if (err) {
  			console.log(err);
  		} else {
        sensorData = data;
  		}
  	});
  }
}

Запускаем метод readSensor с какой-то периодичностью и забираем данные последнего опроса из getData. Там будет много составляющих (x,y,z,a) о положении. Разобраться что к чему, честно, не успел. Были важнее задачи с управлением. Знаю, решение такое себе, но оно имело чисто ознакомительный характер, поэтому и актуальность результата не очень важна.

Raspberry PI Flashlight control

Потихоньку продолжаем наращивать функционал и на этот раз займемся светодиодами. У нас есть два XHP-50 диода и драйвер-контроля (см. раздел «Выбор компонентов»). Они очень хорошо греются, поэтому без радиаторов использовать их никому не рекомендую. На том же сайте, благо, они есть. Главное, не напутать с размером.

Итак, прикручиваем диоды на радиатор, паяем минус одного к плюсу другого (на них есть маркировка) и припаиваем минусовой и плюсовой провода:

Далее смотрим на наш контроллер и тоже паяем.

Питание — 12V плюс и минус, можно запитаться тем же, чем и питаем двигатели. Выводы на диод соединяем с ранее припаянными соответственно L- к минусу, L+ к плюсу. Аналоговый контакт (А) в данной реализации не нужен, оставляем пустым.

Теперь нас интересует цифровой вход (D) и земля (G). Коннектим цифру (D) на GPIO 11 и землю на многострадальный GND (любой, можно один). Теперь возвращаемся к нашей Raspberry PI, создаем файлик light.js и добавляем следующее:

//Наша знакомая библиотека
const Gpio = require('pigpio').Gpio;
//Создаем Gpio для нашего пина
const light = new Gpio(11, {mode: Gpio.OUTPUT});
// Значение можно ставить от 0 до 255 (из доков по драйверу светодиода)
const LIGHT_MIN = 0;
const LIGHT_MAX = 255;
//Нужно будет для вычислений
const LIGHT_DIAPASONE = LIGHT_MAX - LIGHT_MIN;
//Выключаем светодиод изначально (система стартует с включенными на максимум светодиодами)
light.pwmWrite(LIGHT_MIN);
//Экспортируем методы работы
module.exports.light = {
  on: () => {
    //Передаем на драйвер значение 255
light.pwmWrite(LIGHT_MAX);
  },
  off: () => {
//Передаем на драйвер значение 0
    light.pwmWrite(LIGHT_MIN);
  },
//Здесь принимаем значение в процентах от 0 до 100
  set: (val) => {
    if(val < 0 || val > 100) return;
//Вычисляем значение исходя из процента
    val = Math.round(LIGHT_MIN + LIGHT_DIAPASONE / 100 * val);
    console.log("Light:"+val);
//Передаем на драйвер значение
    light.pwmWrite(val);
  }
}

Запустить можем из нашего app.js так же, как и engines:

const light = require('./light.js').light;
light.on();
light.off();
light.set(50);

Видеодемонстрация готового решения:

Если понять главную идею, то все предельно просто: подключил, подал сигнал, смотришь результат. Грубо говоря, это весь функционал контроля, который нам нужен для активизации элементов. Но все это бесполезно без какого-то контроллера, который и будет включать/регулировать все это, а это говорит о том, что надо построить коммуникацию между сервером и клиентом. Значит придумаем протокол :)

Протокол общения

Как вы поняли из первоначальной настройки Raspberry PI, общение будет произведено по сокет подключению. И нужен какой-то набор команд, который будет захардкожен на сервере и клиенте. Так как я сам себе д’артаньян, то решил использовать свой формат, ибо варианты, которые есть, не совсем подходят по критерию вес/читаемость. Строим, основываясь на базе модели управления, а это телефон с Android на борту.

Вот приблизительно и сама модель (программа будет описана чуть ниже). Экран разделен на две части. Левая отвечает за горизонтальную плоскость (вперед и назад), правая — за вертикальную.
Ставите палец в какой-то области — это считается точкой отсчета и контроля парой двигателей, но при этом это точка спокойствия.

Если ведете его вертикально вверх — потихоньку повышается скорость вращения обоих двигателей в прямом направлении с мощностью от 0 до максимума (зависит от расстояния от точки касания до текущей).

Если двигаем вниз: оба двигателя вращаются в реверсном направлении, со скоростью, зависимой от удаления от точки касания.

Если вправо: левый крутится в прямом, правый в реверсном.

То есть по факту нам нужно знать угол отклонения от точки касания (где верх = 90, низ — 90, право 0, лево 180) и коэффициент скорости — удаленность пальца от точки касания (от 0 до 100). Конечные команды выглядит так:

C:L;A:45;V:35;
C:R;A:0;V:100;
C:LIGHT;V:50;

С — любая команда начинается с этой буквы (command);

: — разделитель ключ-значения;

; — разделитель пар ключ-значение;

L — говорит, что нажатие было в левой части экрана;

R — соответственно в правой;

LIGHT — внезапно, свет :)

A — ANGLE угол отклонения;

V — value значение чего-то.

То есть первая команда говорит: «Горизонтальна пара двигателей, направление 45 градусов (левый на максимуме (но максимум — это 35%, исходя из V), правый стоит), со скоростью вращения 35% от максимума».

Вторая соответственно: «Вертикальная пара двигателей, направление 0 градусов (левый на максимуме, правый на максимальном реверсе), с максимальной скоростью вращения». Третья: «Включить свет на 50% яркости».

Так и шлем по сокету на каждое изменение какого-то значения отдельные команды блоками ключ-значение. Далее магическим способом превращаем это в команды на платы управления. Расписывать преобразование этих данных — сильно скучно, здесь и так много текста. Так что каждый может включить воображение или попытаться разобраться в контроллере.

Приложение на Android

Наконец-то мы «доехали» до создания контроллера для всего этого. В целом, общение состоит из «нажал на что-то на экране — передал значение на сервер». Вкратце пройдемся по базовому приложению. Здесь нет ничего необычного и сверхсложного, поэтому весь код выкладывать не буду. При желании зайдете на репозиторий и посмотрите. Также хочу отметить, что все новомодные паттерны MVVM, MVP, VIPER и т. д. пошли лесом, ибо мне надо было рабочее приложение в минимальные сроки, а не выпендриваться. Юайка простая, так что делается максимально просто.

Первым делом создадим активность с вьюхами отображения состояния.

Лаяут будет следующий:

  1. Слой отображения видео (плеер инкапсулирован во фрагмент).
  2. Слой JoystickView — кастомная вьюха, в которой переопределен метод dispatchTouchEvent и в нем обрабатываем нажатие и перемещение пальцев по экрану. Она же рисует UI-линии от нажатия до текущего состояния. Обязательный аспект — поддержка мультитача, так как управление осуществляется двумя пальцами.
  3. Слой с TextView текущей температуры Raspberry PI (если что-то пошло не так и она начинает греться — можно прекратить использование раньше, чем она выключится/сгорит). Благо, такого не было.
  4. Слой отображения данных с гироскопа. Набор TextView в парах label-значение. Выводит «сырые данные» с гироскопа. Планировалось их обрабатывать, но времени не хватило для разбора всего и изобретения крутого отображения.
  5. Слой с SeekBar — управление светодиодом, простой элемент, при перетягивании которого меняется значение от 0 до 100.

Видео Stream

Тут было проделано достаточно много работы для подбора необходимых способов стриминга.

HLS сразу отпал, так как задержка была порядка 10 секунд. При желании можно было добиться 5, но это все равно далеко не то, что надо. В управлении крайне необходимо передать видео с минимальной задержкой. Но передачу организовать не сложно, что со стороны Raspberry, что отображение с Android.

RTMP уже будет потяжелее. Проблема в том, что не было особо простого варианта реализации на Android (на момент конца 2017 года). Есть платные варианты, с которыми тоже повозиться, есть многострадальный VLC, который надо компилить с C++ и настраивать, есть уже собранный VLC как библиотека, который тоже из коробки не хотел проигрывать. Если прибавить ко всему, что это было как хобби и делалось в вечернее послерабочее время, когда голова не сильно свежая и времени ±2 часа, то эти варианты я отбросил.

Зато нашел очень даже рабочее решение, которое подходило по моим параметрам. RPi Camera Viewer for Android — решение, которое получает Raw H.264 поток с камеры и отображает на TextureView c использованием нативного MediaCodec. Если честно, то я до конца не раскрутил всю логику отображения, но собрал и чуть модифицировал под себя для использования. Собственно, главным со стороны Android выступает DecoderThread. Он коннектится по IP и порту, декодит поток и отдает в Surface, а в случае обрыва или ошибки идет рекконект каждые 2 секунды.

Со стороны Raspberry команда запуска потока будет следующая:

raspivid -t 0 -w 1280 -h 720 -hf -ih -fps 10 -o - | nc -k -l 2222

Raspivid — команда, которая осуществляет «захват» видео с подключенной камеры (но не USB, а именно подключенной шлейфом). Параметры выбирал методом «научного» тыка. Качество 1280×720, частота кадров 10fps. Безумно мало, но минимальная задержка.

И весь поток, который транслируется с камеры передается без изменений командой Netcat на 2222 порт.

Приложение на Android коннектится к нему и уже обрабатывает видео, отображая на экране.
Неделю вечеров пришлось потратить на поиск и тестирование таких простых решений, так как общение с Raspberry для меня было в новизну, как и стриминг с Unix-системы.

Управление с экрана и джойстиком

Как уже было сказано ранее, JoystickView передает угол и значение касания экрана на сокет в виде команды типа C:L;A:45;V:35;

Есть поток подключения к сокету (с реконнектами, колбеками и прочим), в котором находится очередь команд. Циклом выбирает их и отправляет на сервер.

В помощь экранному управлению допилил управление джойстиком.

Данный девайс коннектится по Bluetooth и работает как клавиатура. Следовательно, все данные обрабатываются MainActivity методами onKeyDown и onGenericMotionEvent.

Тест управления:

Вроде ничего важного со стороны Android не забыл, если что-то не раскрыл — пишите, объясню, допишу.

Сборка и тестирование конструкций

Теперь мы добрались до следующего шага — засунуть все как-то во что-то (гы-гы). На этапе проектирования и сборки мне помогал один очень хороший человек по имени Сергей. Собственно, он нашел коробку, сделал некую железную платформу, на которую можно было крепить двигатели в разных позициях, и собрал все это вот в такой вариант:

Забегу вперед и скажу, что вариант с 6-ю двигателями был бы продуктивнее, но я не выгребал проектирование четырех, и было решено тестить урезанную версию. Изначально мы решили протестить конструкцию в целом и не стали засовывать электронику в коробку, а просто прикрепили двигатели к платформе, да по двум витым парам подали на каждый из них сигнал из ESC (который оставался всегда на суше).

Вот такой адок получился в итоге:

Был забит болт на потери при передаче (кабеля было 10 метров) и на основные косяки такого решения. Потому основная цель была посмотреть:

  1. Можно ли жить с 4-мя движками?
  2. Можно ли управлять с телефона?
  3. Будет ли затекать вода в коробку?

Но я упустил один важный момент, о котором Серега меня предупреждал. После теста в ванной все эти контакты надо было хорошенько просушить, ибо они — самое слабое звено. А я забил и получил в итоге комбо из 48 мест(!!!) соединения, которые могут (а если могут — обязательно будут) терять контакт.

Здесь как на всех мемасиках ожидание-реальность.

Тест в ванной:

Его сильно кренит из-за проводов, но он способен перемещаться. Ну и чутка перегружен грузами, так как коробка пустая — не рассчитал. А вот следующий тест в «поле» оказался еще хуже:

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

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

Так как никто не был уверен, что на глубине 10+ метров эта конструкция не даст течь и не зальет электронику — решили сделать усиленный вариант «коробка в коробке». Заказали в Китае все необходимое и приступили к дальнейшей сборке:

В коробке были просверлены отверстия для проводов, которые выходили через cable glands (забыл, как они называются по-другому).

Дополнительно была прикручена коробка для диодов и камеры. Естественно, на резиновую прокладку и плотненько зажата винтами. Далее была спаяна плата соединений, с отдельными разъемами под каждый ESC, драйвер диода и гироскоп.

Дабы упростить из без того нагроможденные конструкции, питание сделали одно (для всех узлов) — от LiPO батареи, так как только она способна выдать такой ток разрядки, который покрыл бы и Raspberry, и диоды, и двигатели. Но дополнительно добавили плату уменьшения напряжения с 12V до 5V, которая питала только малину. «Работаем дальше» ©

Получили вот такой внутренний дата-бокс. 4 вывода мотора, 2 диода и шлейф видео. С ним пришлось повозиться больше всего. Правда, в самый последний момент подключения камера не взлетела (на тестах было все хорошо) — где-то таки переломал шлейф во время бесконечных разборок и сборок. Так как уже не было сил это все пересобирать еще раз — решено было забить, да прикрепить на скотч экшн-камеру в водозащитном кейсе и провести новые тестирования.

Кстати, были заменены также гребные винты на максимально большие из тех, которые продаются для моделей, и заменены двигатели на более мощные. На каждый электромотор, который отвечал за горизонтальную плоскость, было прикреплено по 2 винта, просто потому, что они были :)

В качестве роутера был подключен наш NEXX. То есть из Raspberry PI выходит витая пара и коннектится посредством RJ-45 в маршрутизатор. Он же, в свою очередь, раздает Wi-Fi для Android-телефона. На малине забит статический IP адрес, что позволяет не настраивать каждый раз подключение. Правда опять есть проблемы с подключением — если нет нормального покрытия связи, телефон не может присоединиться нормально по IP. Для этого отключал мобильный интернет и пытался присоединиться несколько раз. После подключения открывал SSH на телефоне и запускал команды запуска node сервера (а после всего — выключения системы).

Пришло время новых тестов и, казалось бы, что может пойти не так? Да все :)

По приезде на киевское водохранилище были обнаружены волны нечеловеческих размеров (ну это я так себя утешаю).

И последствия таких заплывов: полностью забитые двигателя всякой плавающей штукой типа водорослей, песком. Тест был снова провален.

Третий и самый успешный тест был произведен уже на спокойном озере, что давало немалые преимущества по сравнению с первыми двумя.

Выводы

Главное, что из этого всего получилось — большой опыт в построении таких вот связок и систем. В процессе разработки было использовано немалое количество различных девайсов, и их управление оказалось намного проще, чем это выглядит издалека.

Конструкция на четырех двигателях не сильно оправдала свои ожидания — управлять таким девайсом крайне тяжело. В идеале надо делать четыре вертикальных двигателя, минимум два горизонтальных. При этом стабилизировать все гироскопом, ибо человек теряется в управлении, и ему надо помогать (как это делают все летающие собратья).

Также все моторы, которые есть в продаже для воздуха очень быстро забиваются песком и прочим, поддаются коррозии отдельных элементов (что логично) и вряд ли подойдут под такие проекты. Конкретно моторов для подводной работы я не нашел (точнее на них может и написано, что waterproof, но это от брызг и глубины до метра).

После этого проекта любой умный дом не кажется таким уж сложным. Сервер, команды на реле, да и все. Главное, время и желание. Остальное придет.

А смысл?

А его нет.

Обещанные ссылки:

Для запуска используем файл app.js.

Всем добра.

LinkedIn

77 комментариев

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

Raspberry Pi можна замінити на Beablebone Black або Beablebone Blue.
beagleboard.org/black
beagleboard.org/black-wireless
beagleboard.org/blue

Перевагою над Raspberry Pi є те що в цих платає є PRU (programmable real-time unit: beagleboard.org/pru ) -тобто ви можете робити будь яку логіку аналогічно як на мікроконтроллері і все працюватиме аналогічно. Наприклад частота PMW не буде змінюватись в залежності від завантаження Linux.

Для апки могли взять Blynk, сэкономили бы пару дней — www.youtube.com/...​arch_query=blynk joystick

Но зачем? Они же еще и удовольствие получали от разработки, а не пытались заказ быстрее заказчику втюхать.

Но зачем?

По той же причине по которой они взяли готовый расп, а не паяли свою.

Блинк мало поможет в том, что они делали. У них же не столько задача где-то отобразить данные с датчиков, а отладить железо и софт. А в этом случае нужно к этим датчикам ручками стукаться, фильтры навешивать, подбирать кучи параметров.

Это только на видео. Вот собрали такое, включили и оно работает. А в реале, датчики шумят, помехи отовсюду горой, одно согласование движков уже не тривиальная задачка (а там что-то софтово решить, где-то резаки крутить отверткой).

Напаять свой расп или написать три строчки кода управления- совершенно разные вещи)
Вы ребята крутые, спору нет.
Лично для меня есть смысл заюзать блинк, если
а) лень разбираться
б) есть какие-то преимущества
Почти все взлетело без особого труда (ну читать доки и в блинке надо было бы)
А есть ли возможность подключить Blynk как библиотеку в андроид апп?
Или можно использовать только через Вашу аппку из гугл плей?

А есть ли возможность подключить Blynk как библиотеку в андроид апп?

Для нас нету смысла, так как мы зарабатываем именно на апках.

Значит для меня тоже нет смысла)
Ибо в чем тогда будет работа?) «Я использовал блинк как сервер, и установил блин из Гугл плей»
Ни статью написать, ни поиграться.
Так как я сам разработчик, то будет несколько позорно так поступать)

Так не интересно)
Я привык больше контролировать то, что происходит
Тем более, что на андроид там не было ничего сложного (кроме плеера, который вряд ли есть в блинке)

Наконец-то инженерная статья на ДОУ.
Как глоток свежего воздуха.

А вы терпеливы. Это же сколько времени ушло всё это сделать. Работа офигительная вами проведена.

Спасибо. 1 год, но это в итерациях «сделал, ждешь месяц деталь из Китая». В целом, можно за месяц такое запилить, если все под рукой.

Крутая статья! Вы молодцы! побольше бы таких на доу!
.... а не всякий высер как кто-то по молодости нюхал апельсины на заводе и втирал их в десна

Спасибо)
Посмотрим насколько это будет популярно)
Есть как-бы мнение, что статья про то, как прогер лапал за сиську бухгалтера на новогоднем корпоративе, будет более читабельно и в «топе»)

Что значит популярно? Там срачи и критика, а вас за что критиковать? За проведенную большую работу и полученный результат?

Вас же, читая, получаешь удовольствие. Вот что можно сделать, если пива меньше бухать.

Ну пиво там как раз часто было при деле)
Правда оно приводило к демагогии на пару часов, а практичного не приносило)))

О, а де про таке можна почитати?

Ціквий проект. Недавно винаймав яхту в чартер, так от чартерні наймають водолаза який пірнає під човен і перевіряє чи на корпусі немає пошкоджень після оренди. Я думаю такий робот з доброю камерою став їм в нагоді. Водолази коштують дорого і беруть погодинно, а такий дрон витрата одноразова і окупався би за кілька тижнів.

Проект интересный, но правило «всё, что бы вы не придумали — уже придумано кем-то» работает в 99.9999999999999[9] процентах случаев)

Для этого им нужны приличные инвестиции. Ниже Фогол скинул ссылку. Можешь прикинуть, сколько стоила разработка того по ссылке.

OpenRov, к примеру, собрал 800 000$ на кикстартере.
Если делать под продажи- то там прорва
Времени и денег

Если бы да кабы. Вы осилите такое? Это совсем другая работа и обычно у инженеров она плохо выходит. Да, инженеры могут сделать многое, но вот в бизнесе они обычно лохи.
Да и вашу поделку нужно будет сильно перерабатывать и многое переделывать, чтобы она кого-то заинтересовала. Пока это хоть и сложная, но игрушка.

Немного не понял претензии, к чему это сказано- хз
Дорогу осилит идущий, как говорится. Была бы цель- была бы реализация.
А так это игрушка. В статье было сказано, что это «чисто унять азарт».
Кто-то написал по поводу того, что я хочу что-то сделать другое?
Я сделал ровно то, что хотел сделать. И получил то, что требовалось.
Или я похож на обычного задрота-инженера, который обычно «лох» в бизнесе?

Это не претензия. а предостережение было

Сорри, неправильно понял.
Нет амбиций на проект. Он в стадии заморозки ибо утомил азарт и Китай убьет вскоре)
Если было бы надо, заменеджить все это можно было. Я сильно инженер, я бы сказал даже слабо)

Дам совет. Продолжай просто дальше развлекаться, как инженер.
Конкурировать в США и Китаем — это фантастика.
А так просто продолжай делать игрушки в свое удовольствие.

Я подобное еще в 90-х проходил, правда в другой области. Сейчас понял, что важно только собственное удовлетворение.

Да много уже подобных подводных «роботов». Вопрос в цене и маркетинге.

www.youtube.com/watch?v=NUbtlDP916U

Під водою звук має непогано передаватись

И да и «а что вы там хотите услышать?») Двигатели дают шум неистовый. Рыбы молчат.

Нажаль, надіслати відео потік не буде можливості.

Вірогідно, так. Зате можна від кабелю відмовитись. З іншого боку, якщо є кабель, навіщо тоді дрону тягати з собою батарею?

Кстати не кто не думал что раз звук под водою хорошо передается, то можно создать приемо-передатчик TCP-IP, только пакеты передавать звуковыми волнами? Можно таким образом наладить связь под водой.

Да. Только вот для того, чтобы обеспечить хотя бы 10 кбод под водой люди диссеры писали. На основе одного из таких диссеров работает связь между китайскими подлоками (военными).
А так ты услышишь много шума и ничего более. И да диссер тот засекреченный, мне его почитать когда-то не дали, но немного по удаленке делал, мелочь там и в стороне от основной работы. Знаю только, что диссер делался челом в ВИЗРУ в Минске в конце жизни совка.
Там громадный объем работы и по передатчику и по приемнику звука и по собственно передаче.

Цікаво, а не можна телефонний модем на 56к підлаштувати для цих цілей? Не для лодок, а для дрона.

Нет. Вопрос тут сложнее и сильно. Я этой технологии и теории не знаю.

А если звуком передавать, а потом звук транслировать в пакеты?

Тут надо много экспериментировать. И нужен подводный передатчик звука, приемник. С обычным динамиком и микрофоном под водой не получится. Нужно изучать теорию сонаров, искать дешевые, малые, гражданские.
И собственно с ЦОС я бы мог ТС помочь, но не с железом, в железе я очень слаб. Если он сможет как инженер, что придумать, то с ЦОC я могу ему помочь.

Я не вижу смысла с этим возиться- дрон без «глаз» бесполезная вещь. А по звуку передать видео поток без задержек- та ещё работа. Да и в теории там проблемы с шумом. Электродвигатели фонят очень сильно

А по звуку передать видео поток без задержек- та ещё работа.

Это уже область фантастики.
По звуку можно только команды управления пропихнуть. Но это море работы.

Если брать именно наши- то да, принцип тот же
Но всего в мире много таких
www.openrov.com
www.blueyerobotics.com
и т.д.
И Китай подключился
www.aliexpress.com/...​archText=underwater drone
Все это уже в серии и с ними тяжело будет конкурировать, если придется

Отличный проект! Очень интересно!
Парочку идей\советов:
1. Правим питание(готовыми решениями): конвертим 12 в 110 на берегу, и питаем дрон по 2 жилам переменным током(имульсник все же легче батареи да и меньше места нужно в боксе) + кабель можно в разы тоньше.
2. В качестве линии передачи берем PLC, обычную пару паверлайн адаптеров(тоже с переделками заморачиваться особо не надо, plug&play) поскольку линк P2P да еще и вне бытовой сети то ширины канала с головой хватит 4К гонять.
3. Вместо RPi можно посмотреть на какие то китайские сетевые камеры с OpenWRT на борту, там обычно легко можно получить доступ к UART (иногда SPI and/or I2C) + микруха на управлени движками и гироскопами(хоть скорости и не космические но RTOS был бы луче debian’a для стабилизации) да и цена «мозгов» падает то не жалко утопить =)
3.1 Если все таки SBC то камеру(ы) цеплять на USB шину(питание считай шаровое), скорости высокие не надо, да и когда камера на шнурке ее легче монтировать + можно крутить хоть на 360 градусов.
С магнитами идея шикарная! Там конечно ювелирно что бы все сделать нужно попыхтеть, но как вариант для синхронизации можно лазерную калибровку прикрутить(стробоскоп) и мотором ловить винт. На кожухи движков поставить москитку, как минимум большая водоросль попадать не будет.

1) Это да. Просто есть несколько моментов:
Платы, которые я находил имеют поддержку тока в 10-20А, чего не хватит на 4 движка, диодов и распберри. Решение засунуть батарею во внутрь было взято за основу по причине а) это был самый быстрый и простой способ (просто прикрутили коробку) б) вес не имел большого значения, т.к. дрон приходилось грузить для имитации нейтральной плавучести
Если бы это был серийный дрон, то скорее всего пришлось бы кидать именно переменным по проводу. Но там еще вопрос какие он даст помехи на сигнал)
2) Да, идея хороша. Можно было бы копнуть в эту степь
3) Ну RPi стоит не дорого, так что тут выиграша скорее всего не будет. Сам вопрос в технологии. В теории можно и usb камеру втулить на 4к и пустить поток по кабелю. Но вот настроить сам стриминг и плеер на андроид — не сильно простая задача (RTSP сервер-клиент или что-то типа этого), с учетом того, что в есть ограниченые ресурсы рук/времени/желания :) (хотя быть может недокопал в эту степь)

С магнитами было весело)
Просто оно бы вышло затратнее и не факт что лучше)
Для «ловли» вращения можно просто примостырить два датчика Холла arduino.ua/...​od186-Datchik_Holla_A3144 на каждую пару двигатель-винт. Стоят они дешево. Но «чем сложнее конструкция, тем больше чему ломаться»
Москитка да, только тут двуяко. Двигатели надо иногда чистить- значит сьемная сетка и т.д.
Для тестов это оверлоад
Да и «братья» тоже без сеток

пришлось бы кидать именно переменным по проводу. Но там еще вопрос какие он даст помехи на сигнал)

никаких? ))

en.wikipedia.org/...​/Power-line_communication

Если PLC — никаких. Если PoE — то может и были бы.
Если вернуться от теории к практике.
Есть источник питания 12V на суше.
Не изобретая велосипед покупается что-то типа этого
Но ему надо 220V. Значит надо купить инвертор, который будет стоять на суше возлк аккума.
Добавляем инвертор, даем с батареи на инвертор, с него на PLC, который должен выступать точкой доступа Wi-Fi(для Android). Если у него нет такой опции- добавляем мини маршрутник, с питанием на 5V и коннектим по ethernet.
От первого PLC идет провод в дрон. Принимаем 220V переменного, но нам еще надо 12V и 5V постоянного.
Следовательно второй PLC стоит внутри коробки, принимает 220 и сигнал, отдает его на малину по ethernet. Но еще надо поставить выпрямитель и две платы понижения напряжения до 12V и 5V
И надо помнить, что 12V постоянного может затребовать 20+A тока, и не каждая плата это потянет.
Если в кратце, для серийного производства пришлось бы морочиться, для тестового это усложняет в разы конструкцию, добавляя много плат и соединений.

Если честно ничего не понял. Единственное что раз у вас потребление может быть больше 12В 20А силового + всякая мелочовка программного то соотв. кабель на 220В потребует больше 1А это собственно всё что я хотел сказать об передаче силового по проводам а ну да ещё учесть КПД силового преобразователя на конце сам цифровой сигнал по силовому кабелю переменного тока технология отработанная.

Если 12В 20А не помещаются в один канал то у вас с этим проблем нет потому как у вас 6 силовых моторов и соотв. это всё легко бьётся на 6 раздельных силовых каналов/плат. Да ещё и головной свет отдельно на 3А правда 6В опять же ж отдельная плата на 2×20 Вт )) насколько я понимаю электричество для передачи мощности 300 Вт по линии 220В вам потребуется сечение кабеля меньше 0,5 мм. Чтобы пощупать что это я специально походил по дому и поискал что это нашёл на бытовом вентиляторе гибкий 2×0,5 мм (в эквиваленте) по таблице по нему можно передать 2А что соотв. с головой по виду он достаточно тонкий и гибкий и не слишком тяжёлый к.м.к. для ваших применений должен хватить только надо уточнить степень защиты в соотв. условиях (полное погружение до 10 м) видимо всё ))

ЗЫ: к.м.к. у вас «слишком гаражные условия» проще взять плату сразу с чипом ethernet и уже через неё пробрасывать дальше тот или иной wired а то «вай фай для андроид...» это что-то очень мудрёное... ))

Ну в теории можно что угодно)
На практике все сложно достать и скомпоновать
Переменный ток усложняет конструкцию)

Кстати я придумал как вам сделать без инвертора на берегу достаточно взять вполне стандартный ups )) к тому же ж свинцовые батареи дешевле.

Упс хорошая идея
Но он тяжёлый) для теста покатит
Я юзал изначально автомобильный аккумулятор, то ещё удовольствие

Отличная статья, где автор показывает как хобби и профессия успешно совмещаются)

Надо делать беспроводный ретранслятор и надводный блок.

Имеется в виду, что внутри wi-fi и что-то типа коаксиалом антенну наверх? Или вообще без провода?

Имеется в виду надводный правучий модуль с wi-fi или чем подальше а от него спускаемый модуль уже на кабеле таки образом позволит отходить от берега а потом уже уходить под воду.

Сложности конечно есть в первую очередь технические и возможно «просто ящицек с 6 рулями» уже не так круто )) плюс вопросы связанные с автономностью сиречь если что надо бы б и достать и кабель тоже как-то сперва травить потом выбирать но задача к.м.к может быть много интереснее + применение шире.

Статья прекрасная. Вдохновляет.

здесь прекрасно все, от детализации до волн нечеловеческих размеров

Автор молодец! Побольше бы таких статей!)

Круто) Было интересно почитать)

Теперь, с опытом построенния этого чуда, осталось построить физический прототип ReVolt, с управлением через андроид приложение и выводом изображения на все тот-же экран %)
после чего находим еще одного такого же сумасшедшего и устраиваем забег. Только работать будет на wifi, чтобы не кары не запутались в проводах

Или просто покупаем машинки за 500грн и делаем то же самое)))

Как человеку не подкованному в паянии, статья о том как из обычной радиоуправляемой машины сделать радиоуправляемую андроидом машину — была бы самое то :)

Не подумал про камеру)
В телефоне нет радиопередатчика и по-этому или искать вай-фай машинку с приложением, или рукожопить все заново. Базируясь на статье- все реально сделать)

wait a minute... а ведь это идея для старт-апа, не? Почему тогда еще никто не сделал?

Где-то встречал уже реализации. Если погуглить, то можно найти. Особенно в Китае))))

www.youtube.com/watch?v=X99RF7amJgY

собрался такую делать, но китайцы с поставками деталей подводят :)

Шикарно сделано :D правда приложение может помочь с интеграцией UE для добавления augmented reality элементов

-___- я сейчас зря выдал эту идею, да?

Я планировал с женой собирать два болида, и устроить трек по нескольким комнатам квартиры, может даже с какими-нибудь магнитными (ну или еще проще — RFID карты приклеить к болиду) метками-чекпоинтами, идея с AR интересная — но немножко overkill, и не взлетит на ресурсах чисто ардуины. Но то всё лирика — надо хоть базовый функционал собрать :)

Ну Raspberry моща, покроет с головой такой функционал. С учетом что в квартире есть вай-фай, то еще проще будет

А зачем ар обрабатывать на машине если есть смартфон?

Потому что arduino не застримит видос из коробки, он сильно прост
Может какие-то доп платы, но это может быть сложнее, чем юзнуть распберри

Есть закон подлости, который говорит, что придет все, кроме нужной. А нужная будет ехать в два раза дольше)

Еще давно на хабре где то уже было такое, да и в ютубе тоже находилось, там еще через 4g линк по городу катался в режиме FPV, сидя у себя за компом. Но нынче уже мало интересно, ввиду доступных полуфабрикатов- запихнул одноплатник за 10$, серву с мотором прицепил, поднял rtsp серв с захватом usb камеры одной строкой, чутка гкода на джабаскрипт с отпракой bson и готово... никакой романтики :)

Подписаться на комментарии