- PVSM.RU - https://www.pvsm.ru -
В этой статье, по многочисленным просьбам мы расскажем как сделать простейший гидроакустический модем: немного цифровой обработки сигналов, немного программирования, немного самодельных печатных плат и капля практической гидрологии.
Всем заинтересованным — милости просим под кат, в реверберирующий мир подводной связи!
А вот релевантная картинка, для привлечения внимания:

«В конечном счете смысл нашего существования — тратить энергию… И по возможности, знаете ли, так, чтобы и самому было интересно, и другим полезно.»
(С) АБС, «Полдень, XXII век»
Сейчас вы можете купить на Aliexpress или eBay практически все, что угодно. Особенно много всякого разного для самостоятельного изготовления чего-либо электронного на основе Arduino. Вы можете сделать (если просто купить неинтересно) мильен-стопервую метеостанцию с подключением к интернет, автоматическую кормушку для кота, контроллер домашней пивоварни, но пока еще вы не можете купить гидроакустический модем, конструктор для его изготовления или хотя бы модуль для адруино. Ну и хорошо! И не надо — сейчас мы расскажем как его сделать, а еще расскажем как он работает.
Мы всей лабораторией долго думали, что можно предложить любителям для самостоятельного изготовления. Что-нибудь очень простое, собрать которое под силу и школьнику, из палки и веревки того, что есть под рукой у каждого, но в то же время обязательно представляющее хотя бы минимальную практическую или учебную ценность.
Что-нибудь обещающее долгое и увлекательное совершенствование, то, что в последствие можно перенести даже на ардуино, будь оно неладно.
Если подходить к вопросу материалистически, то нам хотелось предложить подробный туториал для изготовления некоего простого устройства, которое было бы более-менее в состоянии передавать данные в мелководном водоеме (мелководный гидроакустический канал — наиболее сложный), подразумевало бы максимум изготовление печатной платы при помощи ЛУТ, с общей стоимостью, не превышающей на минималочках пары-тройки сотен рублей.
Вся идея простейшего модема построена на, опять же, простейшем (совпадение?) детекторе определенного тона, про который, я к своему стыду не слышал. Рассказал мне про него совершенно невзначай andrey_9999a [5]. Он, кстати, сделал и плату предусилителя.
В связи с этим мне вспомнилась цитата из книги Леонарда Сасскинда «Битва при черной дыре»:
«Как ценитель вина, я более или менее уверен, что даже с закрытыми глазами смогу отличить красное от белого. Еще более надежно я отличу вино от пива. Но вот дальше вкус меня подведет.»
Могу сказать про себя, что как заправский электронщик я более или менее уверен, что точно смогу спаять два толстых провода. Еще более надежно я отличу горячий паяльник от холодного даже с закрытыми глазами, но вот дальше навык меня подведет. Поэтому все, что касается разработки и изготовления плат — это работа моих товарищей и коллег andrey_9999a [5] и StDmitriev [6].
Итак, вернемся к детектору. Он является упрощенным частным случаем вычисления интеграла Фурье:
В случае цифрового сигнала, для вычисления амплитуды произвольной гармоники потребуется выполнить дискретное преобразование Фурье, для Ардуины это тяжеловато, но хитрость состоит в том, что если взять в качестве несущей частоты Fc такую, что она будет ровно в 4 раза меньше частоты дискретизации Fs, то амплитуду этой гармоники можно вычислять демонически проще.
В этом случае dt = 2π*(Fs/4)/Fs = π/2, и на период несущей приходится всего 4 сэмпла:

Если все сдвинуть на π/4 то сэмплы будут принимать только два значения: √2/2 и -√2/2, для простоты оставим только знаки — «+» и «-».
Суть же метода состоит в том, что синусную фазу мы представляем как последовательность знаков «+» «+» «-» «-», а косинусную как «+» «-» «-» «+».
Пусть входной сигнал лежит в буфере sn, у нас есть два кольцевых буфера усреднения для синусной и косинусной фазы — bs и bc размером N. Указатели головы и хвоста у них общие — bH и bT. В начальный момент времени bH = N-1, bT = 0. Счетчик циклов усреденения C = 0.
Берем из входного буфера по 4 сэмпла и складываем согласно последовательностям знаков.
a = sn(i)
bs(bH) = a
bc(bH) = a
s1 = s1 + a - bs(bT)
s2 = s2 + a - bc(bT)
bH = (bH + 1) % N
bT = (bT + 1) % N
a = sn(i+1)
bs(bH) = a
bc(bH) = -a
s1 = s1 + a - bs(bT)
s2 = s2 - a - bc(bT)
bH = (bH + 1) % N
bT = (bT + 1) % N
a = sn(i+2)
bs(bH) = -a
bc(bH) = -a
s1 = s1 - a - bs(bT)
s2 = s2 - a - bc(bT)
bH = (bH + 1) % N
bT = (bT + 1) % N
a = sn(i+3)
bs(bH) = -a
bc(bH) = a
s1 = s1 - a - bs(bT)
s2 = s2 + a - bc(bT)
bH = (bH + 1) % N
bT = (bT + 1) % N
После каждой обработанной четверки сэмплов проверяем счетчик циклов усреднения и если он перевалил за N, то вычисляем амплитуду cA несущей:
if ++cycle >= N
cA = sqrt(s1 * s1 + s2 * s2)
cycle = 0
end
Вот так это выглядит на идеальном сигнале:

Синим показан сам сигнал, красным — значения амлитуды несущей (все приведено к диапазону -1..1). В данном случае N=2 т.к. нет никаких шумов и все и так отлично работает.
Теперь добавим немного белого шума и посмотрим, как на это отреагирует наш детектор:

Я добавил белого шума таким образом, чтобы соотношение сигнал-шум было равно 0 дБ. На рисунке выше синим показан зашумленный сигнал, зеленым — исходный, а красным — значение амплитуды. В этом случае детектор при N=2 уже ничего не задетектировал, и минимальное N при котором он исправно работет равно 32. Т.е. размер окна обработки в сэмплах составил 32*4 = 128 сэмплов.
То есть, теперь мы можем анализировать входной сигнал и оценивать некий параметр, который количественно показывает наличие частоты, в четыре раза меньше частоты дискретизации. Если задаться неким пороговым значением для этого параметра, то все можно бинаризовать, и говоря по-простому, мы сможем дать ответ на вопрос: присутствует ли заданный тон во входном сигнале или нет?
Это очень хорошо, но нам нужно передавать биты, а биты могут принимать два значения.
Реализовать систему с двумя сигнальными состояниями при помощи одного — так себе идея, поэтому мы не будем кодировать одно из состояний тишиной (паузой). Это бы сильно затруднило детектирование: нужно было бы как-то выделять начало посылки, придумывать как оформить ее конец и т.д.
Вместо этого «1» и «0» мы будем кодировать импульсами разной длины, между битами наличествует т.н. защитный интервал — ведь нам же еще нужно бороться с многолучевым распространением и реверберацией. Говоря простым языком, защитный интервал — это то место (время), где затухнут все отражения предшествующего бита, все послезвучия и эхо.
Забегая вперед, примем к сведению, что при такой структуре сигнала алгоритм работы приемника очень сильно упрощается: ждем когда появился тон, засекаем начало, ждем, когда тон пропал и опять засекаем время — если полученное время больше похоже по длине на «1» то, наверное мы приняли бит со значением «1», если больше похоже на «0» — то видимо мы приняли бит, со значением «0».
В общем, можно сказать, что это некий вариант морзянки.
Для нетерпеливых — пример лежит на GitHub [7]. Написан на скорую руку на C# (потому что для ПК я пишу на нем и мне просто так удобнее и быстрее).
Для воспроизведения и захвата звука с микрофонного входа используется замечательная библиотека NAudio [8].
Вся логика модема находится в классе SUAModem [9] (Simple Underwater Acoustic Modem).
В конструктор передаются следующие параметры:
double sRateHz — частота дискретизации в Герцах;
int wSize — размер окна обработки в сэмплах;
int oneMultiplier — сколько «окон» длится бит со значением «1»
int zeroMultiplier — сколько «окон» длится бит со значением «0»
double eThreshold — порог, скажем о нем позже
Для формирования сигнала из массива байт есть метод ModulateData(byte[] data), который возвращает массив 16-ти битных знаковых сэмплов.
public short[] ModulateData(byte[] data)
{
double alpha = 0;
double phase = 0;
List<short> samples = new List<short>();
BitArray bits = new BitArray(data);
for (int i = 0; i < bits.Length; i++)
{
int sLim = (bits[i]) ? oneDurationSmp : zeroDurationSmp;
alpha = 0;
phase = 0;
for (int sIdx = 0; sIdx <= sLim; sIdx++)
{
alpha = Math.Sin(phase);
phase += delta;
if (phase >= alimit)
phase -= alimit;
samples.Add(Convert.ToInt16(alpha * short.MaxValue));
}
samples.AddRange(new short[defenseIntervalSmp]);
}
return samples.ToArray();
}
В основном цикле по передаваемым битам происходит заполнение списка samples. В зависимсоти от текущего передаваемого бита устанавливается длина sLim формируемого сигнала в сэмплах. После каждого бита добавляется защитный интервал.
Для генерации тона с частотой при заданной частоте дискретизации
соответствующее значение
вычисляется просто:
Для формирования и излучения сигнала есть метод TransmitData(byte[] data), который внутри себя вызывает ModulateData:
public double TransmitData(byte[] data)
{
var samples = ModulateData(data);
double txTime = ((double)samples.Length) / SampleRateHz;
var rawBytes = new byte[samples.Length * 2];
for (int i = 0; i < samples.Length; i++)
{
var bts = BitConverter.GetBytes(samples[i]);
rawBytes[i * 2] = bts[0];
rawBytes[i * 2 + 1] = bts[1];
}
using (var ms = new MemoryStream(rawBytes))
{
using (var rs = new RawSourceWaveStream(ms, new WaveFormat(Convert.ToInt32(SampleRateHz), 16, 1)))
{
using (var wo = new WaveOutEvent())
{
wo.Init(rs);
wo.Play();
while (wo.PlaybackState == PlaybackState.Playing)
{
Thread.SpinWait(1);
}
}
rs.Close();
}
ms.Close();
}
return txTime;
}
О принятии очередного байта класс SUAModem сообщает при помощи события DataReceivedEventHandler.
Входные сэмплы послупают в анализ при помощи метода ProcessInputSignal(short[] data), где записываются в кольцевой буфер ring. Анализ происходит в отдельном потоке, в методе Receiver.
А сам приемник живет в методе Receive:
private void Receive()
int a;
while (rCnt >= 4)
{
a = ring[rRPos];
rRPos = (rRPos + 1) % rSize;
rCnt--;
dRing1[rHead] = a;
dRing2[rHead] = a;
s1 += a - dRing1[rTail];
s2 += a - dRing2[rTail];
rHead = (rHead + 1) % windowSize;
rTail = (rTail + 1) % windowSize;
a = ring[rRPos];
rRPos = (rRPos + 1) % rSize;
rCnt--;
dRing1[rHead] = a;
dRing2[rHead] = -a;
s1 += a - dRing1[rTail];
s2 += -a - dRing2[rTail];
rHead = (rHead + 1) % windowSize;
rTail = (rTail + 1) % windowSize;
a = ring[rRPos];
rRPos = (rRPos + 1) % rSize;
rCnt--;
dRing1[rHead] = -a;
dRing2[rHead] = -a;
s1 += -a - dRing1[rTail];
s2 += -a - dRing2[rTail];
rHead = (rHead + 1) % windowSize;
rTail = (rTail + 1) % windowSize;
a = ring[rRPos];
rRPos = (rRPos + 1) % rSize;
rCnt--;
dRing1[rHead] = -a;
dRing2[rHead] = a;
s1 += -a - dRing1[rTail];
s2 += a - dRing2[rTail];
rHead = (rHead + 1) % windowSize;
rTail = (rTail + 1) % windowSize;
if (++cycle >= windowSize)
{
cycle = 0;
currentEnergy = Math.Sqrt(s1 * s1 + s2 * s2) / windowSize;
double de = currentEnergy - prevEnergy;
#region analysis
if (skip > 0)
skip -= windowSize * 4;
else
{
if (isRise)
{
if (de > -Threshold)
{
riseSmp += windowSize * 4;
}
else
{
// analyse symbol
isRise = false;
double oneDiff = Math.Abs(oneDurationSmp - riseSmp);
double zeroDiff = Math.Abs(zeroDurationSmp - riseSmp);
if (oneDiff > zeroDiff)
{
// Mostly likely "0"
AddBit(false);
}
else
{
// Mostly likely "1"
AddBit(true);
}
samplesSinceLastBit = 0;
skip = defenseIntervalSmp / 2;
}
}
else
{
if (de > Threshold)
{
isRise = true;
riseSmp = windowSize * 4;
}
}
}
#endregion
prevEnergy = currentEnergy;
if (bPos > 0)
{
samplesSinceLastBit += 4 * windowSize;
if (samplesSinceLastBit >= defenseIntervalSmp * 2 + zeroDurationSmp + oneDurationSmp)
{
DiscardBits();
}
}
}
}
}
Из кода видно, что анализ ведется по 4 сэмпла, при желании можно сохранять состояние и вести обработку и по одному сэмплу, что будет полезно при переносе на какой-нибудь немощный МК.
По мере поступления данных вычисляется значение амлитуды s на частоте sRateHz/4. Вычисляется разница между предыдущим и текущим значением амплитуды и затем сравнивается с заданным порогом, подобранным экспериментально. Пример позволяет в реальном времени этот порог менять.
Резкое увеличение амплитуды свидетельствует о начале «бита», резкий (несколько менее резкий — из-за реверберации) спад — о завершении «бита».
После приема очередного бита отрабатываем защитный интервал — пропускаем заданное количество сэмплов — в них всякие эхо, они нам будут только мешать.
Итак, со структурой сигнала все понятно, как его принимать тоже ясно. Дело за малым — научиться излучать сигнал в воду и принимать его из воды.
Если у вас еще нет гидроакустических антенн, то самое время их сделать по нашему предыдущему туториалу [10].
У меня они остались с того раза, так что я этот шаг пропускаю.
Ту антенну, которая предназначена для передачи мы подключаем к плате усилителя с алиэкспресс [11]. Для нескольких десятков метров (может даже для сотни) нам этого вполне хватит. Никаких хитростей тут нет — выход звуковой карты ноутбука идет на вход усилителя, который питается от свинцового АКБ 12 вольт 4 Ач. На выход подключена наша гидроакустическая передающая антенна из пьезопищалки. В моем случае это выглядит вот так:


На фото выше, на экране есть небольшой спойлер следующей статьи. В следующий раз на этих же железках мы снова будем пытаться передавать «видео» звуком через воду, но совершенно иным способом, чем в прошлый раз [12].
С приемной антенной несколько сложнее. Хоть пьезопищалки и очень чувствительны, все же этого недостаточно. Нам придется собрать плату предусилителя с фильтром на полосу 5-35 кГц.
Коэффициент усиления мы берем 1000.
Схема, дизайн печатной платы и список компонентов предусилителя лежит у нас на GitHub: схема [13], дорожки — верхний слой [14] и нижний слой [15], BOM [4].
Технология ЛУТ [16] обсуждалась стотыщмильенов раз, но дайте же и нам внести свою лепту.

Берем оттуда пару страниц и печатаем на них слои при помощи лазерного принтера.

Совмещаем при помощи иголочек и склеиваем по одной стороне, как показано на фото:

Перед применением утюга смачиваем тонер изопропиловым спиртом:

Утюжим через сложенный вчетверо лист А4:

Размачиваем теплой водой под краном:

И отмываем остатки бумаги. После чего получаем заготовку, готовую к травлению:

Лишнее отрезаем при помощи ножниц по металлу или кому чем удобнее.
Травим в хлорном железе. Специально для статьи мы развели свежее, оно оказалось настолько забористое что от будущей платы активно идут пузырики:

В результате, после травления и отмывки тонера получаем такой полуфабрикат:


После напайки компонентов и отмывки плата выгладит вот так.
А так выглядит приемная часть в сборе. Питание осуществляется от такого же свинцового АКБ 12 вольт:

На всякий случай приведем здесь АЧХ текущей реализации фильтра:

А вот еще проект [17] для этого фильтра, созданный в приложении Qucs [18]
Для подключения к ноутбуку используем обычный Jack 3.5 мм, самый кончик — сигнал, средний — не подключен, земля — к земле прах к праху. Все усиления и любые эффекты микрофона нужно отключить, а громкостью придется поиграться, чтобы достичь оптимального уровня. Зашкал должен происходить при касании подключенной к предусилителю антенны пальцем и легком поглаживании.
Если просто положить одну пьезу на другую без усилителя и предусилителя и подключить их к аудиовходу и выходу, то все работает идеально. Ниже представлен отрезок сигнала и можно даже на глаз определить где какие значения битов:

Синим показан сам сигнал, красным — разница между текущим и предыдущим значениями амплитуды (фронт), зеленым — разница между предыдущим и текущим значениями (спад). Без труда можно «демодулировать» эту часть посылки: 1 0 0 0 1 1 0. Ноль у нас в два раза дольше единицы, а длительность защитного интервала равна длительности нуля.
Далее, также без усилителя и предусилителя опускаем наши антенны в металлический бак, размерами 3х1.5х1.5. У нас такой стоит в лаборатории, и мы завели себе правило, что не занимаемся никакой связью, если она хоть как-то не в состоянии работать в этом баке. Дело в том, что в таком замкнутом объеме энергии особо некуда деваться — звук чудесно и многократно отражается от металлических стенок и в точке приема получается каша. А с учетом того, что мы обычно проверяем готовые девайсы с энергетикой, рассчитанной на тысячи метров, можете представить что там творится.
Например, два наших модема RedLINE [19] устойчиво работают в этом баке только на расстоянии не больше двух метров, а два uWAVE [20]-а стабильно работают примерно на 1 метре. При том что первый в открытой воде работает до 8000 метров, а второй — до километра [21].
Конечно, все коммерческие продукты не используют такие примитивные схемы модуляции, о которой идет речь в статье и устроены гораздо сложнее, но нам сейчас важно понять азы и с пользой поделать что-то руками.
В общем, опускаем антенны в бак на расстояние порядка 50 сантиметров и получаем уже нечто гораздо менее благообразное, чем при непосредственном контакте антенн:

Хотя здесь использован значительно более долгий защитный интервал, все равно видно, что эхо гуляет почти до следующего бита, фронты и особенно спады сильно размыты. Но все еще можно определить содержание сообщения: 1 0 0 0 1 1 0
В обоих случаях я передавал сообщение «123» и эти семь бит принадлежат символу единицы.
Выглядело это примерно так, потом интерфейс был немного переделан

Из скрина выше видно, что при тех настройках, передача сообщения «Hello, habr [22]!!! :-)» состоящее из 19 байт занимает 9.132 секунд, то есть скорость передачи составила 16,6 бит/с. К слову сказать, чтобы модем работал в нашем баке пришлось увеличить защитный интервал так, что скорость передачи упала до ~3 бит/с.
Мы проверяли самоделку в плавательном бассейне, где устойчиво она заработала на 10 метрах.

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


Антенны приемника и передатчика опускались прямо с берега, глубина там резко уходит с 0.5 до 2 метров. В опыте, который показан на фото выше были, как ни странно, самые плохие условия, дистанция там была всего порядка 5 метров — это вообще была первоначальная настройка. Из 20 переданных сообщений по 3 байта, в шести из них было побито по одному байту.
Потом, когда мы подключили приемник ко второму ноутбуку и перенесли на другой берег пруда (дистанция порядка 30 метров) передача проходила значительно лучше — на 40 сообщений размером от 3 до 13 байт было всего пару ошибок.

На следующем фото на карте видны места, где располагались антенны.

Как и обещал, за мало рублей мы собрали рабочее устройство. Хоть практическая ценность его сомнительна, но сам процесс изготовления и настройки на водоеме будет очень полезен начинающим. На описанном методе детектирования несущей вполне можно придумать разных простых навигационных систем для любительского применения, а что особенно приятно, вычислительная сложность позволяет реализовать метод на простом микроконтроллере.
Чтобы не быть голословным относительно построения навигационных систем на простых сигналах, взгляните на интересную работу [23], в которой построили полноценную длиннобазисную навигационную систему. В этой системе определяют положение пингера, который периодически передает свою глубину. Значение глубины при этом кодируется расстоянием между двумя простыми импульсами на определенной частоте. Так что да-да, горшки не боги обжигают, дорогу осилит идущий, терпение и труд, учиться, учиться, учиться — вот это вот все.
Возможно, при наличии времени мы сделаем DIY-проект по позиционированию автономного пингера, излучающего простые сигналы. Нечто подобное, но не DIY мы уже делали на базе наших модемов uWAVE [24], о чем даже попытались снять видео [25]. Будет очень интересно услышать ваши мнения на этот счет — очень важно иметь подтверждение, что делаешь что-то не напрасно.
Тем не менее, возвращаясь к основной теме, отметим, что можно было бы улучшить в предложенной схеме:
На этом заседание объявлю закрытым, а если вас заинтересовала тема, вот список наших предыдущих статей:
Подводный GPS с нуля за год [26]
Подводный GPS на подводном роботе: опыт использования [27]
Мы сделали самый маленький в мире гидроакустический модем [20]
К вопросу о влиянии цианобактерий на речевые функции президента [28]
Делаем простую гидроакустическую антенну из мусора [10]
Сеанс передачи видео звуком через воду с разоблачением [29]
Подводный «GPS» на двух приемопередатчиках [30]
Навигация под водой: пеленгуй не пеленгуй — обречен ты на успех [31]
Подводный GPS: продолжение [32]
Как всегда с удовольствием выслушаем замечания и предложения, обоснованную критику и одобряющие возгласы )
Железки далеко не убирайте — в следующий раз мы с их помощью будем опять передавать «видео» через воду.
Автор: Aleksandr Dikarev
Источник [33]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/diy/317680
Ссылки в тексте:
[1] Пример кода: https://github.com/AlekUnderwater/SimpleUnderwaterAcousticModem/tree/master/SRC
[2] от часов или открытки: https://www.aliexpress.com/item/5PCS-LOT-15cm-cable-length-diameter-35mm-Piezo-Ceramic-Element/32887402292.html?spm=2114.search0104.3.51.2fa41c2eDCvl13&ws_ab_test=searchweb0_0,searchweb201602_1_10065_10068_10890_319_10546_317_10548_10696_453_10084_454_10083_10618_10307_537_536_10059_10884_10887_321_322_10915_10103_10910,searchweb201603_52,ppcSwitch_0&algo_expid=fc0df690-2647-4172-8edc-978e564b3ec7-7&algo_pvid=fc0df690-2647-4172-8edc-978e564b3ec7&transAbTest=ae803_5
[3] такой: https://www.aliexpress.com/item/1pcs-TDA2030A-Module-Single-Power-Supply-Audio-Amplifier-Board-Module/32847983961.html?tt=sns_none&aff_platform=default&cpt=1557766052396&sk=XXxRqxY&aff_trace_key=24a5a2a3375a462ebee4006e2341e3bb-1557766052396-09983-XXxRqxY&terminal_id=6eb28f235e794d9897c6710be47d8866
[4] комплектующие: https://github.com/AlekUnderwater/SimpleUnderwaterAcousticModem/blob/master/Preamplifier_board/BOM.xlsx
[5] andrey_9999a: https://habr.com/ru/users/andrey_9999a/
[6] StDmitriev: https://habr.com/ru/users/stdmitriev/
[7] пример лежит на GitHub: https://github.com/AlekUnderwater/SimpleUnderwaterAcousticModem
[8] NAudio: https://github.com/naudio/NAudio
[9] SUAModem: https://github.com/AlekUnderwater/SimpleUnderwaterAcousticModem/blob/master/SRC/C%23/SUAModem.cs
[10] нашему предыдущему туториалу: https://habr.com/ru/post/431302/
[11] плате усилителя с алиэкспресс: https://www.aliexpress.com/item/1pcs-TDA2030A-Module-Single-Power-Supply-Audio-Amplifier-Board-Module/32847983961.html?tt=sns_none&aff_platform=default&cpt=1557765605290&sk=XXxRqxY&aff_trace_key=5b7cbf3c89fc4d6fbe6aa2e870630181-1557765605290-02601-XXxRqxY&terminal_id=6eb28f235e794d9897c6710be47d8866
[12] прошлый раз: https://habr.com/ru/post/408871/
[13] схема: https://github.com/AlekUnderwater/SimpleUnderwaterAcousticModem/blob/master/Preamplifier_board/piezo_preamp_1000_5-35kHz_schematic.pdf
[14] верхний слой: https://github.com/AlekUnderwater/SimpleUnderwaterAcousticModem/blob/master/Preamplifier_board/Top_70x25_mm.bmp
[15] нижний слой: https://github.com/AlekUnderwater/SimpleUnderwaterAcousticModem/blob/master/Preamplifier_board/Bottom_70x25_mm.bmp
[16] Технология ЛУТ: https://habr.com/ru/search/?q=%D0%9B%D0%A3%D0%A2#h
[17] проект: https://github.com/AlekUnderwater/SimpleUnderwaterAcousticModem/blob/master/Preamplifier_board/filter.sch
[18] Qucs: http://qucs.sourceforge.net/
[19] RedLINE: https://github.com/ucnl/Docs/blob/master/RU/Modems/RedLINE/RedLINE_Specification_ru.pdf
[20] uWAVE: https://habr.com/ru/post/428367/
[21] до километра: https://www.youtube.com/watch?v=Z1bVerVecY0
[22] habr: https://habr.com/ru/users/habr/
[23] интересную работу: https://www.semanticscholar.org/paper/UNDERWATER-ACOUSTIC-POSITIONING-SYSTEMS-BASED-ON-Alcocer-Oliveira/134a4e769a6a64c6f5bc0f0efda9ed2a93893bdb
[24] uWAVE: https://github.com/ucnl/Docs/blob/master/RU/Modems/uWAVE/uWAVE_Specification_ru.pdf
[25] снять видео: https://www.youtube.com/watch?v=UHfTv7TtABU&t=11s
[26] Подводный GPS с нуля за год: https://habr.com/ru/post/370083/
[27] Подводный GPS на подводном роботе: опыт использования: https://habr.com/ru/post/449072/
[28] К вопросу о влиянии цианобактерий на речевые функции президента: https://geektimes.ru/post/293681/
[29] Сеанс передачи видео звуком через воду с разоблачением: https://habr.com/post/408871/
[30] Подводный «GPS» на двух приемопередатчиках: https://habr.com/ru/post/421977/
[31] Навигация под водой: пеленгуй не пеленгуй — обречен ты на успех: https://habr.com/ru/post/405845/
[32] Подводный GPS: продолжение: https://habr.com/ru/post/403891/
[33] Источник: https://habr.com/ru/post/451800/?utm_source=habrahabr&utm_medium=rss&utm_campaign=451800
Нажмите здесь для печати.