Привет, глубокоуважаемые!


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

Всем заинтересованным — милости просим под кат, в реверберирующий мир подводной связи!

А вот релевантная картинка, для привлечения внимания:



«В конечном счете смысл нашего существования — тратить энергию… И по возможности, знаете ли, так, чтобы и самому было интересно, и другим полезно.»
(С) АБС, «Полдень, XXII век»

Для экономии вашего времени — краткое содержание


  • Гидроакустические модемы пока не продают на Aliexpress
  • Есть простой и нетребовательный к вычислительным ресурсам метод детектирования тона, частота которого в 4 раза меньше частоты дискретизации; Для реализации хватит и Arduino
  • Пример кода для PC лежит на GitHub
  • Приемную и передающие антенны делаем из пьезопищалок по 10 р штука
  • Покупаем (или делаем сами) платку усилителя на TDA2030 на Ali за 50 рублей
  • Делаем ЛУТ-ом предусилитель, с суммарной стоимостью ~100 рублей
  • Подключаем и идем на водоем
  • Радуемся

Мотивационная прелюдия


Сейчас вы можете купить на Aliexpress или eBay практически все, что угодно. Особенно много всякого разного для самостоятельного изготовления чего-либо электронного на основе Arduino. Вы можете сделать (если просто купить неинтересно) мильен-стопервую метеостанцию с подключением к интернет, автоматическую кормушку для кота, контроллер домашней пивоварни, но пока еще вы не можете купить гидроакустический модем, конструктор для его изготовления или хотя бы модуль для адруино. Ну и хорошо! И не надо — сейчас мы расскажем как его сделать, а еще расскажем как он работает.

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

Что-нибудь обещающее долгое и увлекательное совершенствование, то, что в последствие можно перенести даже на ардуино, будь оно неладно.

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

Что мы будем делать сегодня?


  • вспомним, как сделать подходящую гидроакустическую антенну и изготовим парочку;
  • одну из антенн подключим к ПК через усилитель на TDA за ~50 рублей и получим передатчик;
  • для второй сделаем при помощи ЛУТ предусилитель за ~100 рублей;
  • напишем (я уже все написал и положил на Git) простой модем на C# и испытаем все на ближайшем водоеме;

Что нам для этого понадобится?


  • два пьезоэлемента. Например, от часов или открытки;
  • кабель RG-174/U (или аналогичный) ~5 метров;
  • безуксусный герметик;
  • водостойки лак;
  • фольгированный текстолит, в общей сложности примерно 100x200 мм;
  • усилитель на TDA2030 (например, такой, за 50 рублей);
  • комплектующие для предусилителя

Как оно работает?


Вся идея простейшего модема построена на, опять же, простейшем (совпадение?) детекторе определенного тона, про который, я к своему стыду не слышал. Рассказал мне про него совершенно невзначай andrey_9999a. Он, кстати, сделал и плату предусилителя.

В связи с этим мне вспомнилась цитата из книги Леонарда Сасскинда «Битва при черной дыре»:
«Как ценитель вина, я более или менее уверен, что даже с закрытыми глазами смогу отличить красное от белого. Еще более надежно я отличу вино от пива. Но вот дальше вкус меня подведет.»
Могу сказать про себя, что как заправский электронщик я более или менее уверен, что точно смогу спаять два толстых провода. Еще более надежно я отличу горячий паяльник от холодного даже с закрытыми глазами, но вот дальше навык меня подведет. Поэтому все, что касается разработки и изготовления плат — это работа моих товарищей и коллег andrey_9999a и StDmitriev.

Итак, вернемся к детектору. Он является упрощенным частным случаем вычисления интеграла Фурье:

$\int_0^Tf(x)sin(\omega t)dt$


В случае цифрового сигнала, для вычисления амплитуды произвольной гармоники потребуется выполнить дискретное преобразование Фурье, для Ардуины это тяжеловато, но хитрость состоит в том, что если взять в качестве несущей частоты Fc такую, что она будет ровно в 4 раза меньше частоты дискретизации Fs, то амплитуду этой гармоники можно вычислять демонически проще.

В этом случае dt = 2?*(Fs/4)/Fs = ?/2, и на период несущей приходится всего 4 сэмпла:



Если все сдвинуть на ?/4 то сэмплы будут принимать только два значения: v2/2 и -v2/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. Написан на скорую руку на C# (потому что для ПК я пишу на нем и мне просто так удобнее и быстрее).

Для воспроизведения и захвата звука с микрофонного входа используется замечательная библиотека NAudio.

Вся логика модема находится в классе SUAModem (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)
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 формируемого сигнала в сэмплах. После каждого бита добавляется защитный интервал.

Конечно...
Многие могут заметить, что при генерации сигнала можно было бы обойтись и без функции синуса, но данный пример позволяет, изменив соотвествующим образом значение delta, изменить и частоту генерируемого тона.

Для генерации тона с частотой $F_n$ при заданной частоте дискретизации $F_s$ соответствующее значение $\delta$ вычисляется просто:

$\delta=2\pi F_n/F_s$



Для формирования и излучения сигнала есть метод TransmitData(byte[] data), который внутри себя вызывает ModulateData:

public double TransmitData(byte[] data)
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()
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. Вычисляется разница между предыдущим и текущим значением амплитуды и затем сравнивается с заданным порогом, подобранным экспериментально. Пример позволяет в реальном времени этот порог менять.

Резкое увеличение амплитуды свидетельствует о начале «бита», резкий (несколько менее резкий — из-за реверберации) спад — о завершении «бита».

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

Железная часть модема


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

Если у вас еще нет гидроакустических антенн, то самое время их сделать по нашему предыдущему туториалу.

У меня они остались с того раза, так что я этот шаг пропускаю.

Ту антенну, которая предназначена для передачи мы подключаем к плате усилителя с алиэкспресс. Для нескольких десятков метров (может даже для сотни) нам этого вполне хватит. Никаких хитростей тут нет — выход звуковой карты ноутбука идет на вход усилителя, который питается от свинцового АКБ 12 вольт 4 Ач. На выход подключена наша гидроакустическая передающая антенна из пьезопищалки. В моем случае это выглядит вот так:





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

С приемной антенной несколько сложнее. Хоть пьезопищалки и очень чувствительны, все же этого недостаточно. Нам придется собрать плату предусилителя с фильтром на полосу 5-35 кГц.
Коэффициент усиления мы берем 1000.

Схема, дизайн печатной платы и список компонентов предусилителя лежит у нас на GitHub: схема, дорожки — верхний слой и нижний слой, BOM.

Технология ЛУТ обсуждалась стотыщмильенов раз, но дайте же и нам внести свою лепту.

Фото технологического процесса
Итак, берем подходящий журнал, у нас под рукой оказался только этот:



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



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



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



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



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



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



Лишнее отрезаем при помощи ножниц по металлу или кому чем удобнее.

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



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





После напайки компонентов и отмывки плата выгладит вот так.



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



Небольшой дисклеймер по поводу фильтра
Если читатель захочет изменить полосу, то предлагаем пересчитать фильтр 8-ого порядка, собранный на дешевом 4-х канальном операционнике TL084C (DA2 на схеме), резисторах R10-R13, R15-R23 и конденсаторах C5-C8, C11, C12, C14 и С15.

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



А вот еще проект для этого фильтра, созданный в приложении Qucs

Опыты и испытания


Для подключения к ноутбуку используем обычный Jack 3.5 мм, самый кончик — сигнал, средний — не подключен, земля — к земле прах к праху. Все усиления и любые эффекты микрофона нужно отключить, а громкостью придется поиграться, чтобы достичь оптимального уровня. Зашкал должен происходить при касании подключенной к предусилителю антенны пальцем и легком поглаживании.

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



Синим показан сам сигнал, красным — разница между текущим и предыдущим значениями амплитуды (фронт), зеленым — разница между предыдущим и текущим значениями (спад). Без труда можно «демодулировать» эту часть посылки: 1 0 0 0 1 1 0. Ноль у нас в два раза дольше единицы, а длительность защитного интервала равна длительности нуля.

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

Например, два наших модема RedLINE устойчиво работают в этом баке только на расстоянии не больше двух метров, а два uWAVE-а стабильно работают примерно на 1 метре. При том что первый в открытой воде работает до 8000 метров, а второй — до километра.
Конечно, все коммерческие продукты не используют такие примитивные схемы модуляции, о которой идет речь в статье и устроены гораздо сложнее, но нам сейчас важно понять азы и с пользой поделать что-то руками.

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



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

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



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

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



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





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

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



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



Заключение и дальнейшие изыскания


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

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

Возможно, при наличии времени мы сделаем DIY-проект по позиционированию автономного пингера, излучающего простые сигналы. Нечто подобное, но не DIY мы уже делали на базе наших модемов uWAVE, о чем даже попытались снять видео. Будет очень интересно услышать ваши мнения на этот счет — очень важно иметь подтверждение, что делаешь что-то не напрасно.

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

  • сделать вычисление порога адаптивным
  • анализировать ширину сигналов автоматически
  • попробовать использовать разные длины для разных битовых комбинаций
  • прикрутить обожебоже помехоустойчивое кодирование
  • перенести все это на ардуино
  • громкость и порог приходится долго и нудно подбирать, поэтому хорошо бы добавить в предусилитель АРУ

На этом заседание объявлю закрытым, а если вас заинтересовала тема, вот список наших предыдущих статей:

Подводный GPS с нуля за год
Подводный GPS на подводном роботе: опыт использования
Мы сделали самый маленький в мире гидроакустический модем
К вопросу о влиянии цианобактерий на речевые функции президента
Делаем простую гидроакустическую антенну из мусора
Сеанс передачи видео звуком через воду с разоблачением
Подводный «GPS» на двух приемопередатчиках
Навигация под водой: пеленгуй не пеленгуй — обречен ты на успех
Подводный GPS: продолжение

P.S.


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

P.P.S.


Железки далеко не убирайте — в следующий раз мы с их помощью будем опять передавать «видео» через воду.

Комментарии (21)


  1. Jem-Kasha
    15.05.2019 13:33
    +2

    Всех толковых железячников с Хабра выпилили народным голосованием. Теперь комментировать некому. )))
    Я занимался эхолотами некоторое время. Вижу в этой статье много уделено программным вещам (сайт же программеров), а вот элементарные требования фундаментальной физики пошли побоку.
    Но комментировать это я конечно же не буду. Ищите сами. А то здесь за правду карают программисты. ) Ну его…


    1. AlekDikarev Автор
      15.05.2019 13:40

      Мы старались сделать все как можно проще, чтобы мог повторить даже школьник. Это же все-таки proof-of-concept, который оставляет простор для улучшения. Если у вас есть полезные для дела комментарии и критика — будем рады услышать, более того, это же может помочь другим людям.


      1. Costic
        15.05.2019 19:52

        Не могли бы вы прокомментировать конструкцию и принципы работы эхолотов и гидролокаторов, например, Hummingbird Helix (не реклама). Это первое, что попалось в поиске с заоблачной ценой и интересным функционалом.
        P.S. Рыбкам от ультразвука плохо не будет?


        1. AlekDikarev Автор
          15.05.2019 21:01

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


        1. dragonnur
          17.05.2019 23:59

          Чтобы кому-то/чему-то стало от УЗ нехорошо, надо ППМ свыше 0.1 Вт/кв.см в месте попадания в облучаемую тушку.


  1. aproof
    15.05.2019 14:13
    +1

    3 бит/с выглядит скромно. Какие решения могут помочь увеличить скорость обмена, пусть и не тривиальные? Увеличение частоты несущей, одно из очевидных решений, но с недостатком — высокое поглощение на дальних дистанциях.


    1. AlekDikarev Автор
      15.05.2019 14:18

      Ну, 3 бит/сек это в самых неблагоприятных условиях. В пруду вполне работало на 16 бит/сек.
      Нетривиальные решения стоят демонических денег как правило это тысячи долларов. Вот в одной из предыдущех статей я приводил примеры.
      Расширение спектра, если сказать совсем кратко.


    1. andrey_9999a
      15.05.2019 14:29
      +1

      Команду Пли! передать хватит. Шутка. У нас есть вариант простой передачи под водой с увеличением скорости, но это запланировано в одной из следующих статей этого миницикла.


  1. prilichny
    15.05.2019 17:01
    +1

    в магазине ypapa продают всякое, в том числе для развлечений на воде.
    вот интересно, если приобрести там батискаф (вроде есть такое) — можно будет его с помощью такой системы опустить на дно карьера? иными словами, радиус действия каков?


    1. AlekDikarev Автор
      15.05.2019 17:05

      Навскидку, в текущем исполнении десятки метров при благополучных условиях (мы проверяли на ~30м). В гидроакустике, тем более в мелководной все зависит от большого числа параметров. Если в качестве передатчика взять пьезу посерьезнее и после усилителя поставить повышающий трансформатор то сотни метров думаю вполне обеспечит.


  1. antonsosnitzkij
    15.05.2019 19:43
    +1

    В плане тонового детектора может кстати подойти алгоритм Герцеля
    Получается в статье реализована амплитудная модуляция и демодуляция, правильно ли я Вас понимаю?


    1. AlekDikarev Автор
      15.05.2019 20:33

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


      1. antonsosnitzkij
        15.05.2019 20:51

        Разве? мне просто казалось что раз это по своей сути обычный БИХ-фильтр, то реализовать его гораздо легче. Насчет разъяснения да, возможно, хотя вот по той ссылке, которую в том комменте оставил, мне объяснение очень нравится, хотя я и слабоват по матчасти.


    1. AlekDikarev Автор
      15.05.2019 20:34

      Забыл ответить про модуляцию. Да, некий выражденный ее случай


      1. antonsosnitzkij
        15.05.2019 20:57
        +1

        В одно время запарились с коллегой по терминологии и проверили пару источников — строго говоря у вас манипуляция, т.к. используются дискретные уровни модуляции)


        1. AlekDikarev Автор
          15.05.2019 21:21

          Строго говоря не совсем манипуляция. Если бы одно из значений кодировалось паузой — то да, но здесь скорее некое подобие ШИМ у которого период заполнен синусом. Причем имеют место только два варианта скважности.
          Вот тут спрашивали как мол можно ускорить, так вот самый простой способ — увеличить «алфавит», т.е. ввести например 2^n вариантов скважности, и тогда один импульс будет уже нести n бит вместо одного. Но конечно, в этом случае их будет сложнее различать после прохождению через канал, и помехоустойчивость еще снизится


          1. antonsosnitzkij
            15.05.2019 22:07

            Хмм… А если заменить паузу на другую частоту? чтобы было FSK, например


            1. AlekDikarev Автор
              15.05.2019 22:29

              А смысл? Если просто сделать FSK «в лоб» по помехоустойчивости будет скорее даже хуже (защитный интервал!), а по сложности, тем более для школьников — гораздо сложнее. Они замучаются все это настраивать, а потом оно еще нигде толком работать не будет ).


  1. rPman
    16.05.2019 08:34

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


  1. BalinTomsk
    17.05.2019 22:08

    А если в модем впилить RFM95 — понизить частоту и передающий радиотракт заменить на n пьезокристалов?


    1. AlekDikarev Автор
      17.05.2019 22:35

      Если бы все было так просто, то коммерческие гидроакустические модемы не стояли бы тысячи долларов. Частоту нужно будет понизить до нескольких килогерц. У лоры там всякий GFSK ну и вот мы опять там же, где и начали. Условия канала в радиосвязи и акустике сильно отличаются.