docs.unavlab.com

ГлавнаяНаши проекты для образованияACubes: Руководство пользователя

logo image
www.unavlab.com
support@unavlab.com
A3S ACubes
Руководство пользователя

Семейство устройств A3S
Руководство пользователя

Содержание

0. Для кого и зачем эта коробка с кубиками?

В первую очередь ACubes задумывался для применения в сфере образования и подготовки инженерных кадров.

A³S (или ACubes, «Акустические кубики») — это конструктор, набор элементарных функциональных элементов, на основе которых можно создавать макеты практически любых типов гидроакустических навигационных систем и систем связи:

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

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

Мы сознательно не ограничиваем список самих «кубиков», поскольку он изначально задуман как пополняемый. Он будет расширяться в зависимости от сценариев применения — например, при сборке антенной решётки или приёмопередатчика для измерения наклонной дальности.

1. A3T и A3R

Это импульсный одноканальный (одночастотный) передатчик и одночастотный приёмник.

Передатчик A3T

Передатчик A³T излучает импульсы фиксированной частоты и длительности при изменении состояния на своём цифровом входе, которым управляет пользователь.

Приёмник A3R

Приёмник A³R может улавливать эти импульсы и передавать информацию пользователю, изменяя состояние своего цифрового выхода.

Особенности работы

Эти два устройства спроектированы таким образом, что могут объединяться в стек и использовать общую приёмо-передающую антенну, например, RT-1.332820-1. В такой конфигурации получается приёмо-передатчик.

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

Возможности масштабирования

Разъёмы, смонтированные по длинным краям плат, образуют шину, позволяющую объединить один передатчик и до 12 приёмников. При этом выходы всех приёмников будут доступны на свободном разъёме.

Таким образом можно строить и изучать различные конфигурации антенных решёток. Если 12-элементной антенной решётки недостаточно, можно использовать любое количество стеков, в каждом из которых может быть до 12 модулей A³R.

Для удобного объединения до 24 приёмников существует специальная кросс-плата A³R-CB2. Естественно, можно использовать любое количество таких плат.

1.1. О гидроакустических антеннах

Для работы с модулями A³S доступны антенны двух типов:

  1. Приёмо-передающие - совместимы как с модулями A³R, так и с A³T
  2. Приёмные - предназначены исключительно для работы с модулями A³R

Особенности выбора антенн

При использовании устройства только в режиме приёма рекомендуется выбирать приёмные антенны, так как они:

Специализированные приёмные антенны

Антенны серии R-1.d3505-1:

Антенны сделаны так, чтобы их легко можно было объединить друг с другом

Приёмо-передающие антенны

Лаборатория подводной связи и навигации предлагает несколько моделей:

Модель Характеристики
RT-1.332820-1 Наиболее доступное и компактное решение
RT-2.332820-1 Свешиваемая антенна для надводного оборудования (2 пьезоэлемента)
RT-1.524525-1 Модель с повышенной чувствительностью

Правила эксплуатации

  1. Механическая защита:
    • Избегайте ударных нагрузок
    • Не допускайте неравномерного нагружения
    • Антенны с крепёжным пазом должны фиксироваться только за него
    • Запрещается перекрывать рабочую поверхность антенны
  2. Электрическая безопасность:
    • Перед подключением снимайте возможный заряд (закорачивайте выводы)
  3. Уход и обслуживание:
    • Не используйте агрессивные растворители (ацетон, изопропанол)
    • Особенно осторожно обращайтесь с полиуретановыми покрытиями

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

1.2. Проект 1 - Передаем и принимаем

Самый простой сценарий, в котором задействованы один приёмник и один передатчик.

1.2.1. Требуемый набор оборудования

Наименование Количество Примечание
1 Модуль A³R 1  
2 Модуль A³T 1  
3 Антенна приёмная R-1.d3505-1 1  
4 Антенна приёмо-передающая RT-1.332820-1 1  
5 Плата с микроконтроллером (например, Arduino Nano) 2 Можно заменить кнопкой для инициации передачи
6 Провода Dupont Female-Female или Male-Female, 25+ см 4  

Подключение антенн

  1. Подключите приёмную антенну R-1.d3505-1 к модулю A³R:
Подключение приемной антенны
  1. Подключите приёмо-передающую антенну RT-1.332820-1 к модулю A³T:
Подключение приемопередающей антенны

1.2.2. Настройка передатчика

Принцип работы:
Схема подключения к Arduino Nano:
Контакт на XS2 Контакт на Arduino Nano
1 (GND) GND
4 (Инициация передачи) 10 (D10)
Скетч для передачи (1 импульс в секунду):
#define TX_PIN 10      // Пин инициации передачи
#define LED_PIN 13     // Индикаторный светодиод

void setup() {
  pinMode(TX_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(TX_PIN, HIGH); // Исходное состояние
}

void loop() {
  digitalWrite(TX_PIN, LOW);  // Начало передачи
  digitalWrite(LED_PIN, HIGH);
  delay(10);                 // Длительность импульса 10 мс
  
  digitalWrite(TX_PIN, HIGH); // Окончание передачи
  digitalWrite(LED_PIN, LOW);
  delay(990);                // Общий период 1 секунда
}

Примечание: минимальный интервал между передачами - 40 мс

1.2.3. Настройка приёмника

Принцип работы:
Схема подключения к Arduino Nano:
Контакт на XS3 Контакт на Arduino Nano
2 (GND) GND
1 (Строб приёма) 2 (D2)
Скетч для приёма:
#define RX_PIN 2       // Пин детектирования приёма
#define LED_PIN 13     // Индикаторный светодиод

void setup() {
  pinMode(RX_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(RX_PIN), rxDetected, FALLING);
}

void rxDetected() {
  digitalWrite(LED_PIN, HIGH);
  delay(100);         // Светодиод горит 100 мс при приёме
  digitalWrite(LED_PIN, LOW);
}

void loop() {
  // Основной цикл не требуется
}

1.2.4. Тестирование системы

  1. На воздухе:
    • Разместите антенны на расстоянии 10-15 см друг от друга
    • При успешной передаче светодиоды на обеих платах Arduino будут синхронно мигать
  2. В водной среде:
    • Обеспечьте заглубление антенн не менее 1 метра от поверхности
    • Избегайте пузырей воздуха возле рабочих поверхностей антенн
Лабораторная установка

1.3. Кратко о многолучевости и защитных интервалах

Многолучевость и методы борьбы с ней представляют собой обширную область исследований. В данном разделе мы рассмотрим лишь основные принципы.

1.3.1. Суть явления многолучевости

Явление многолучевости можно сравнить с акустическим эхом. Звуковой сигнал от источника распространяется сферическим фронтом, при этом:

  1. Прямой луч - кратчайший путь от источника к приёмнику
  2. Отражённые лучи - сигналы, отразившиеся от:
    • Дна водоёма
    • Поверхности воды
    • Подводных объектов
  3. Преломлённые лучи - сигналы, изменившие направление из-за:
    • Неоднородностей водной среды
    • Изменения скорости звука на разных глубинах

1.3.2. Проблемы, вызванные многолучевостью

  1. Ошибки измерения:
    • Ложное определение наклонной дальности
  2. Эффект “эхо-петли”:
    • В системах маяков-ответчиков возможно возникновение бесконечного цикла “запрос-ответ”
    • Особенно критично при использовании одной частоты для передачи и приёма

1.3.3. Методы борьбы (на примере ACubes)

Для простых сигнальных систем наиболее эффективным решением является защитный интервал:

Параметр Описание
Принцип работы После детектирования сигнала приёмник временно прекращает обработку входящих сигналов
Длительность Определяется экспериментально для конкретных условий
Факторы влияния Глубина, рельеф дна, наличие объектов, свойства водной среды

Рекомендации по настройке:

  1. Начинайте с интервала 50-100 мс для небольших акваторий
  2. Постепенно увеличивайте интервал до исчезновения ложных срабатываний
  3. Для точных измерений может потребоваться калибровка статической ошибки

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

1.4. Проект 2 - Собираем приемопередатчик и измеряем наклонную дальность

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

1.4.1. Требуемый набор оборудования

Наименование Количество Примечание
1 Модуль A3R 2  
2 Модуль A3T 2  
3 Антенна приемопередающая RT-1.332820-1 2  
4 Любая плата с МК, например, Arduino Nano 2  
5 LCD-экран, например MT-204S 1 Для отображения измеренного времени и дальности, но можно выводить и в COM-порт
6 Провода Dupont Female-Female или Male-Female, 25+ см 15  

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

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

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

1.4.2. Запрашивающее устройство

Сначала соберем “бутерброд” из модулей A3R и A3T. Зададим адрес приемника на шине, установив джампер P1. Это сделано для того, чтобы все подключение к плате Arduino было на разъеме XS2. Оплетку и минус антенны спаиваем вместе. Платы приемника и передатчика соединяем перемычками из отрезков проводов через разъемы XS1.

Подключение общей антенны к модулям приемника и передатчика

Далее, подключаем сборку кубиков к плате Arduino. Для этого потребуется 4 провода папа-мама.

Подключение “бутерброда” к плате Arduino Nano
Номер/Наименование контакта на XS2 Номер/Наименование контакта на Arduino Nano
1 / GND GND
2 / Строб при начале передачи 3 / INT1
4 / Инициация передачи импульса 10
6 / Строб приемника №1 2 / INT0

Если вы планируете использовать LCD-экран МЭЛТ МТ-20S4S или совместимый, то необходимо соединить пины следующим образом:

Номер контакта на экране Номер/Наименование контакта на Arduino Nano
1 GND
2 5V
4 8 (D8)
5 9 (D9)
10 4 (D4)
11 5 (D5)
12 6 (D6)
13 7 (D7)

Кроме того, необходимо на плате экрана соединить контакты 1-5 и 2-18, а также контакты 2-3 между собой. Сопротивление между контактами 2-3 задает контрастность экрана, и в некоторых случаях простого их замыкания может оказаться недостаточно.

Ниже представлен скетч для управляющей платы Arduino:

1.4.2.1. Скетч - Инициирует передачу и измеряет время между запросом и ответом

Если использование экрана не планируется, необходимо закомментировать строчку #define USE_LCD. Скорость звука задана константой 1500.0, для более точного значения предлагаем обратиться к нашему онлайн-калькулятору скорости звука в воде: Толковый калькулятор скорости звука в воде

#define USE_LCD

#ifdef USE_LCD
#include "LiquidCrystal.h"
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // RS, E, D4-D7
#define X_MAX              (20) // Число символов на строчку экрана
#define MSG_LINE           (3)  // Номер строки для сообщения
#define W_LINE             (0)  // Номер стоки для отображения прогресса
#endif

// Пин-назначения
#define TX_CONTROL_PIN     10   // Пин управления передатчиком (активный HIGH)
#define TX_STROBE_PIN      3    // Пин строба передатчика (ожидаем FALLING edge)
#define RX_STROBE_PIN      2    // Пин строба приемника (ожидаем FALLING edge)

// Параметры системы
#define ANSWER_DELAY_MS    500    // Фиксированная задержка ответа маяка [мс]
#define SOS_MPS            1500   // Скорость звука в воде [м/с]
#define MAX_DISTANCE_M     500    // Максимальная измеряемая дальность [м]
#define PULSE_WIDTH_MS     10     // Длительность управляющего импульса [мс]

#define PAUSE_MS           (1000) // Пауза между измерениями
#define TIMEOUT            (2 * 1000000L * MAX_DISTANCE_M / SOS_MPS + ANSWER_DELAY_MS * 1000L)

#ifdef USE_LCD
#define TKS_PER_CHAR       ((TIMEOUT - ANSWER_DELAY_MS * 1000L) / X_MAX)
#endif


// Глобальные переменные
volatile uint32_t tor = 0;  // Время излучения сигнала
volatile uint32_t toa = 0;   // Время приема ответного сигнала
volatile bool rx_strobe = false; // Флаг получения строба

// Обработчик прерывания по стробу передатчика
void txStrobeISR() {
  tor = micros();
}

// Обработчик прерывания по стробу приемника
void rxStrobeISR() {
  toa = micros();
  rx_strobe = true;
}

void setup() {
  
#ifdef USE_LCD
  lcd.begin(20, 4);
  lcd.clear();
  lcd.print(F("Starting..."));  
#endif

  Serial.begin(9600);
  Serial.println(F("Starting..."));
  
  // Настройка пинов
  pinMode(TX_CONTROL_PIN, OUTPUT);
  digitalWrite(TX_CONTROL_PIN, HIGH);
 
  pinMode(TX_STROBE_PIN, INPUT);
  pinMode(RX_STROBE_PIN, INPUT);

  // Настройка прерываний
  attachInterrupt(digitalPinToInterrupt(TX_STROBE_PIN), txStrobeISR, FALLING);
  attachInterrupt(digitalPinToInterrupt(RX_STROBE_PIN), rxStrobeISR, FALLING);

  delay(1000);
}

void loop() {

#ifdef USE_LCD
  lcd.setCursor(0, W_LINE);
  lcd.print("                    ");
#endif

  // 0. Сброс
  tor = 0;

  // 1. Инициируем передачу
  digitalWrite(TX_CONTROL_PIN, LOW);
  
  // 2. Ждем строб передатчика (прерывание установит tor)
  while (tor == 0) {
    // Ожидание...
  }

  // 3. Возвращаем состояние пина, управляющего передачей
  digitalWrite(TX_CONTROL_PIN, HIGH);
  
  // 4. В течение фиксированной задержки ответа не обрабатываем приемник
  delay(ANSWER_DELAY_MS);

  toa = 0;
  rx_strobe = false;

  // 5. Ждем строб приемника с таймаутом
#ifdef USE_LCD
  int c_idx = 0;
  uint32_t tks = micros();
#endif

  while (!rx_strobe && (micros() - tor < TIMEOUT)) {
    // Ожидание...

#ifdef USE_LCD
    
    if ((micros() - tks) >= TKS_PER_CHAR) {
      
      lcd.setCursor(c_idx, W_LINE);
      lcd.print(")");

      if (c_idx < X_MAX) c_idx++;
      tks = micros();
    }
    
#endif
  }
  
  // 6. Если сигнал получен - вычисляем дальность
  if (rx_strobe) {
    // Корректно обрабатываем переполнение micros()
    uint32_t tof;
    if (toa > tor) {
      tof = toa - tor;
    } else {
      tof = (0xFFFFFFFF - tor) + toa;
    }
    
    // Вычитаем фиксированную задержку маяка и делим на 2 (туда и обратно)
    tof = (tof - ANSWER_DELAY_MS * 1000L) / 2;
    
    // Рассчитываем дальность
    float srn = tof * 1e-6 * SOS_MPS;
    
#ifdef USE_LCD
    lcd.setCursor(0, MSG_LINE);
    lcd.print("                    ");
    lcd.setCursor(0, MSG_LINE);
    lcd.print(srn, 1);    
    lcd.print(" m");
#endif

    Serial.println(srn, 1);

  } else {

#ifdef USE_LCD
    lcd.setCursor(0, MSG_LINE);
    lcd.print("      TIMEOUT       ");
#endif

    Serial.println("TIMEOUT");
  }
  
  // Пауза между измерениями
  delay(1000);
}

1.4.3. Маяк-ответчик. Вариант 1 - без Arduino

Скажем сразу: этот вариант практически никогда не используется на практике из-за опасности попадания в цикл, когда маяк будет “самозапрашиваться” собственным ответным сигналом.

Здесь нам необходимо собрать такой же “бутерброд”, как и для запрашивающего устройства, с тем лишь отличием, что мы устанавливаем джампер P0, который замыкает выход приемника и вход передатчика. Строб от приемника при получении сигнала станет стробом, инициирующим передачу. Также не забудем установить джампер для задания адреса приемника на шине - это позволит вывести его на разъем XS2.

Джампер P0 соединяет выход приемника и вход передатчика

Антенну подключаем таким же образом, как и для запрашивающего устройства: оплетка и минус спаяны, перемычками соединены разъемы XS1 приемника и передатчика. Отметим, что питание и в случае запрашивающего устройства, и в случае маяка-ответчика необходимо подавать на передающий модуль, чтобы избежать прохождения существенных токов по шине в момент излучения.

1.4.4. Маяк-ответчик. Вариант 2 - с Arduino и фиксированной задержкой

В этом случае в скетче для Arduino запрашивающего устройства необходимо задать какое-то ненулевое значение ANSWER_DELAY_MS. И у платы приемника, и у платы передатчика длительность защитного интервала составляет 40 мсек. Соответственно, выбираемая длительность фиксированной задержки должна быть больше этого значения. В нашем примере мы установили значение 500 мс, что подойдет для большинства небольших акваторий с длительным “хвостом” отражений.

Кроме изменения значения ANSWER_DELAY_MS в скетче запрашивающего устройства не потребуется никаких изменений. А к маяку-ответчику теперь необходимо убрать джампер P0 и подключить вторую плату Arduino Nano, согласно следующей таблице:

Номер/Наименование контакта на XS2 Номер/Наименование контакта на Arduino Nano
1 / GND GND
4 / Инициация передачи импульса 10
6 / Строб приемника №1 2 / INT0

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

1.4.4.1. Скетч - Фиксированная задержка ответа
#define A3R_STATE_PIN     (2)
#define A3T_TX_ENGAGE_PIN (10)
#define LED_PIN           (13)

#define ANSWER_DELAY_MS    (500L) // Фиксированная задержка ответа на ответчике, [мс]
#define DEAD_TIME_MS       (500L) // Защитный интервал после излучения

#define TX_STROBE_DURATION_MS  (10L)

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  pinMode(A3T_TX_ENGAGE_PIN, OUTPUT);
  digitalWrite(A3T_TX_ENGAGE_PIN, HIGH);

  pinMode(A3R_STATE_PIN, INPUT_PULLUP);
}

void loop() {
  if (digitalRead(A3R_STATE_PIN) == LOW) {
    delay(ANSWER_DELAY_MS);
    digitalWrite(A3T_TX_ENGAGE_PIN, LOW);
    digitalWrite(LED_PIN, HIGH);
    delay(TX_STROBE_DURATION_MS);
    digitalWrite(A3T_TX_ENGAGE_PIN, HIGH);
    delay(DEAD_TIME_MS);
    digitalWrite(LED_PIN, LOW);    
  }
}

1.4.5. Эксперименты

1.4.5.1. На столе

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

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

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

TOF, c
1 0.001054
2 0.001182
3 0.001024
4 0.001052
5 0.001148
6 0.001174
7 0.000966
8 0.001154
9 0.001004
10 0.001044
11 0.001282
12 0.001170

Среднее значение времени распространения по 150 измерениям равно 0.001096 с, что эквивалентно расстоянию 1.64 м при скорости звука 1500 м/с. Диапазон изменения величины TOF составляет от 0.000886 до 0.001308 с, или от 1.33 до 1.96 м соответственно.

Интересно выглядит распределение величины статической ошибки - это очень похоже на т.н. Гауссову сместь (Gaussian Mixture), т.е. смесь нормальных (Гауссовых) распределений. Мультимодальность может говорить о наличии нескольких сценариев, по которым происходит процесс.

Мультимодальность в распределении величины статической ошибки

ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ: Определить и устранить причины этой статической ошибки - интересная и увлекательная задача, и мы не можем лишить читателя удовольствия сделать это самостоятельно.

Мы же, для упрощения учтем измеренную статическую ошибку, путем вычитания ее среднего значения: введем #define MAGIC_STATIC_S (0.001096253), и будем вычитать это значение при расчете наклонной дальности:

    float srn = ((tof * 1e-6) - MAGIC_STATIC_S) * SOS_MPS;

Подытожим: в результате экспериментов “на столе” мы:

Теперь можно переходить к водным экспериментам.

1.4.5.2. В тазу

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

Вот, к примеру, вариант “лабораторной установки”. Антенны в нем расположены на расстоянии 40 см друг от друга.

“Лабораторная установка”

Распределение измеренной дальности имеет уже несколько иной вид:

Распределение измеренного времени распространения

Размер выборки не позволяет сделать однозначные выводы, но здесь есть намек на нормальное распределение. Данную гипотезу, увеличив размер выборки, мы предлагаем проветить пользователям самостоятельно. И если эта гипотеза подтвердится, в несколько ином свете выгладит мультимодальность в распределении, полученном по измерениям на воздухе.

Если перейти от времени к дальности, то для данного эксперимента получается диапазон от, фактически, нуля: -0.08 м до 2.07 м. Среднее значение и мода 0.58 м и 0.52 м соответственно. Это некоторым образом отличается от фактического расстояния в 0.4 м между антеннами, но в таких условиях малого объема не стоит ожидать высокой точности и повторяемости результата.

Подытожим:

1.4.5.3. Плавательный бассейн

Даже в небольшом плавательном бассейне объемом ~100 м3 уже появляется возможность провести количественные оценки макета оборудования более тщательно.

Хорошая согласованность непосредственного измерения с акустическими

Антенны можно разместить вдоль одной и той же стенки. Очевидно, более крупные бассейны с мягким полимерным покрытием являются более благоприятными для акустических экспериментов. В ходе экспериментов были выполнены измерения в диапазоне от 0.8 до 8 метров через фиксированные интервалы 0.8 м - соответствующие ширине бардюрной плитки, покрывающей борт бассейна.

Результат измерения дальности на фактическом расстоянии между антеннами 8 метров

Распределение измеренного времени распространения, выполненное по 150 измерениям имеет такой вид:

Предположительно бимодальное распределение величины измеренного времени распространения. Размер выборки 150

Снова распределение имеет мультимодальный, или даже бимодальный вид. При этом, все измерения располагаются в диапазоне от 7.8 до 8.9 м, а среднее значение 8.2 хорошо согласуется с фактическим расстоянием 8 м.

ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ: Стоит отметить, что в случае мультимодального распределения не вполне корректно говорить о среднем значении всей выборки. Разобраться в этом вопросе мы также предлагаем пользователю самостоятельно.

Подытожим:

1.4.5.4. Водоем

Напомним, что максимальная практическая дальность кубиков A³R и A³T согласно спецификациям составляет 300 м. Естественно это не значит что в любых, даже самых неблагоприятных условиях оборудование позволит достичь заявленных показателей, ровно не значит это и того, что на удалении 301 м, устойчиво работающая до этого связь многовенно прекратится.

Например, при проверке на максимальную дальность, передатчик, излучающий сигнал 1 раз в секунду располагался на заякоренном плоту, а приемник постепенно удалялся от него на весельной лодке, заметные перебои в приеме начинали происходить при достижении расстояния 350-370 метров. Условия эксперимента нельзя назвать ни идеальными ни очень сложными. Водоем представляет собой затон р. Волга, длиной порядка 3 км и шириной от 400 до 200 метров в разных местах. Песчаное дно, судоходство средней интенсивности, существенное количество металлических конструкций на дне.

На этом же водоеме проводились эксперименты с обсуждаемым макетом оборудования. Маяк-ответчик располагался на заякоренном плоту из плотного вспененного материала сначала на удалении порядка 80 метров от лодочной пристани, а потом был перемещен на расстояние 156 метров. В обоих случаях расстояние фиксировалось при помощи лазерного дальномера.

Дальность 80 м. Хорошая согласованность непосредственного измерения с акустическими
Дальность 156 м. Хорошая согласованность непосредственного измерения с акустическими

При проведении экспериментов на водоемах, полезно вести запись сигналов. Например, в обсуждаемых испытаниях гидрофон, на который велась запись, располагался в непосредственной близости от антенны запрашивающего устройства и ниже преставлены сами записи и снимки экрана, на которых представлены случайные фрагменты с одним циклом “запрос-ответ” - для дальностей 80 и 156.

ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ: При желании, читатель может сам проанализировать записи:

10-06-2025, Красноармейский затон, г. Волгоград. A³S наклонная дальность, 80 м

10-06-2025, Красноармейский затон, г. Волгоград. A³S наклонная дальность, 156 м

Дальность 80 м. Фрагмент записи из положения запрашивающей системы
Дальность 156 м. Фрагмент записи из положения запрашивающей системы

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

Если учесть фиксированную задержку ответа в 500 мсек, а остаток поделить на два - путь “туда-обратно”, а еще учесть определенную в п. 1.4.5.1. статическую ошибку в 1.096 мсек и скорость звука 1500 м/с, то значение наклонной дальности будут:

((0.610-0.500) / 2 - 0.001096) * 1500 = 80.86 м, и
((0.711-0.500) / 2 - 0.001096) * 1500 = 156.6 м

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

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

4-х миллисекундный сигнал “гуляет” по акватории еще 250 миллисекунд

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

ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ: Что же до статистического анализа измерений наклонной дальности, то мы предлагаем пользователю провести его самому. Будет интересно сравнить результаты экспериментов, проведенных в разных водоемах и разных условиях - погрешность, процент успешных измерений, оценить влияние скорости звука и т.п. Например, в ледовых условиях гораздо проще обеспечить статичное положение запрашивающего устройства и маяка-ответчика, а также более точно измерить фактическое расстояние между ними.

Подытожим:

1.5. Проект 3 - Гидроакустический модем

Со словом “модем” имеется определенная путаница, особенно, когда речь идет о гидроакустических модемах. Сам термин “модем” является производным от МОДулятор и ДЕМодулятор. Сейчас под этим скорее понимается устройство для передачи и приема цифровых данных. Так же часто можно встретить неудачный перевод на английский - “sonar modem”, что, конечно же неверно, т.к. sonar - это буквально означает “sound(sonic) navigation and ranging”, что скорее относится к гидролокации, или к эхолокации.

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

Кодирование передаваемых данных будет осуществляться задержкой между двумя последовательными импульсами. По предыдущим экспериментам мы помним, что требуется некоторый защитный интервал, иначе приемник будет постоянно срабатывать пока в акватории не затухнут все послезвучания. В п. 1.4.5.4. vы опытным путем установили, что сигнал затухает до такого уровня, что уже не детектируется приемником, в течение примерно 200-250 миллисекунд.

Начнем со значения минимального интервала между двумя импульсами в 300 миллисекунд. Это значит, что приняв первый импульс, приемник засекает время и в течение 300 миллисекунд не анализирует состояние линии. К примеру, если мы хотим передавать порциями по 8 бит, то необходимо выбрать некий интрвал и разбить его на 256 значений, нулевое значение будет соответствовать минимальной задержке - 300 мс, а значение 256 - максимально возможной. После второго, “стопового” импульса так же необходимо выдержать какой-то защитный интервал и крайне желательно сделать его отличным от первого интервала. Далее, мы из технических характеристик модуля передатчика знаем, что длительность одного импульса составляет 4 миллисекунды, поэтому имеет смысл выбирать разницу между двумя соседними значениями больше, чем 4 мс. В нашем эксперименте мы примем это значение равным 8 мс - в два раза больше длительности импульса.

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

1.5.1. Требуемый набор оборудования

Наименование Количество Примечание
1 Модуль A3R 2  
2 Модуль A3T 2  
3 Антенна приемопередающая RT-1.332820-1 2  
4 Любая плата с МК, например, Arduino Nano 2  
5 Провода Dupont Male-Female или Female-Female, 15+ см 6  

Дополнительно, как и для предыдущих опытов, потребуются источники питания для “кубиков”. В качестве источника питания удобно использовать сборку 3S из Li-Ion или LiFePO4 аккумуляторов. Также потребуются два ПК, или один ПК с возможностью подключения двух плат Arduino. Еще будет нужно какое-нибудь терминальное ПО, чтобы была возможностью посылать данные в последовательный порт и отображать данные, пришедшие из порта. Например, вполне подойдет утилита ‘Serial monitor’ из Arduino IDE, но если предполагается использовать один и тот же ПК для подключения обоих модемов, то это будет затруднительно. Для работы в Windows vожно использовать нашу простенькую утилиту uConsole.

1.5.2. Подключение

Коль скоро требуются все те же возможности, что и в предыдущих экспериментах, то подключение модема по сути идентично подключению маяка-ответчика из п. 1.4.4..

Для удобства приведем эту информацию еще раз:

Номер/Наименование контакта на XS2 Номер/Наименование контакта на Arduino Nano
1 / GND GND
4 / Инициация передачи импульса 10
6 / Строб приемника №1 2 / INT0

Наш экспериментальный набор выглядит таким образом:

Два гидроакустических модема

1.5.3. Скетч модема

Как видно по коду, скетч получается не очень сложным. Мы принимаем интервал нулевого значения равным 300 мс, защитный “постфиксный” интервал после второго импульса - 420 мс, а расстояние между двумя соседними значениями ровно в два раза больше длительности импульса - 8 мс.


#define A3R_STATE_PIN          (2)
#define A3T_TX_ENGAGE_PIN      (10)
#define LED_PIN                (13)

#define TX_STROBE_DURATION_MS  (10L)

#define SS_PRE_DEAD_TIME_MS    (300L)
#define SS_POS_DEAD_TIME_MS    (420L)
#define SS_TIME_SLOTS          (256L)
#define SS_TIME_SLOT_MS        (8L)
#define SS_MAX_TIME_MS         (SS_TIME_SLOTS * SS_TIME_SLOT_MS + SS_PRE_DEAD_TIME_MS + TX_STROBE_DURATION_MS)

bool receiving = false;
uint32_t r_str_time = 0;
uint32_t r_stp_time = 0;
float r_byte = 256;

void strobe() {
  digitalWrite(A3T_TX_ENGAGE_PIN, LOW);
  digitalWrite(LED_PIN, HIGH);
  delay(TX_STROBE_DURATION_MS);
  digitalWrite(A3T_TX_ENGAGE_PIN, HIGH);
  digitalWrite(LED_PIN, LOW);
}

void setup() {

  Serial.begin(9600);

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  pinMode(A3T_TX_ENGAGE_PIN, OUTPUT);
  digitalWrite(A3T_TX_ENGAGE_PIN, HIGH);

  pinMode(A3R_STATE_PIN, INPUT_PULLUP);

}

void loop() {

  while (Serial.available()) {

    receiving = false;
    
    uint8_t b = Serial.read();
    uint32_t ss_time = SS_PRE_DEAD_TIME_MS + SS_TIME_SLOT_MS * b - TX_STROBE_DURATION_MS;

    strobe();
    delay(ss_time);

    strobe();
    delay(SS_POS_DEAD_TIME_MS);
  }

  int r_state = digitalRead(A3R_STATE_PIN);
  if ((r_state == LOW) && !receiving) {

    r_str_time = millis();
    receiving = true;
    delay(SS_PRE_DEAD_TIME_MS);

    bool is_timeout = false;
    while ((digitalRead(A3R_STATE_PIN) != LOW) && (!is_timeout)) {
      is_timeout = millis() - r_str_time > SS_MAX_TIME_MS;
    }

    if (!is_timeout)
    {
      r_stp_time = millis();

      float duration_ms = r_stp_time - r_str_time - SS_PRE_DEAD_TIME_MS;
      r_byte = duration_ms / SS_TIME_SLOT_MS;

      if ((duration_ms >= 0) && (r_byte <= 255)) {
        Serial.write((uint8_t)round(r_byte));
        delay(SS_POS_DEAD_TIME_MS);
      } 
    }

    delay(10);

    receiving = false; 
  }
}

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

  1. излучается стартовый импульс
  2. выдерживается пауза, складывающаяся из минимальной (“нулевой”) задержки
  3. задержки кодирующей значение передаваемого байта
  4. затем следует стоповый импульс
  5. выдерживается “постфиксная” задержка

Приемник работает так:

  1. проверяется состояние строба приемника
  2. если состояние активно (пин в логическом состоянии 0) - засекается момент времени по встроенным часам
  3. выдерживается защитный интервал в 300 мс
  4. ожидается приход второго (стопового) импульса с отслеживанием превышения интервала ожидания
  5. если второй импульс приходит во время - засекается момент времени его прихода
  6. значение принятого байта вычисляется как деление разности времен прихода второго и первого импульсов на 8 мс

У нас же получился такой результат на воздухе, при расстоянии порядка 70 см между антеннами:

Жрунал обмена между двумя модемами

По записи легко и непринужденно можно “демодулировать” сигнал “вручную”. Вот, например, запись сделанная на воздухе:

Жрунал обмена между двумя модемами

Расстояние между фронтами импульсов по записи 686 миллисекунд. Вычитаем их них 300-миллисекундную фиксированную зержку и делим на 8: (686 - 300) / 8 = 48.25. Округляем 48.25 и получаем значение передаваемого байта - 48, то есть ASCII-код цифры 0.

ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ:

  1. Можно попробовать поменять различные временные значения с целью уменьшения длительности передачи, а соответственно увеличения скорости передачи данных.
  2. Также было бы полезно вычислить и определить экспериментально получившуюся скорость передачи.
  3. В примере выше мы получили дробное значение 48.25, что будет с приемником, если выполнять только целочисленные операции? Что будет, если полученное значение окажется не 48.25, а, скажем, 48.52?

Подытожим:

1.6. Проект 4 - Антенная решетка: измерение угла прихода сигнала

Если вы не знаете, какой размер выборки вам подойдет, то можно взять число 216
О. В. Верходанов, Астрофизик

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

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

Мы будем делать угломерную систему на основе антенны из 4 (четырех) приемников. Конечно, в предельном случае хватило бы и двух, но, как мы уже упомянули, чтобы добиться приемлемого результата с двумя “ушами” нужен хотя бы рептильный мозг, а у нас нет никакого. Поэтому качество будем компенсировать количеством - это распространенная практика в природе, социальной жизни и технике.

Предлагаем кратко обозначить план мероприятий. Во-первых, чтобы понять, на каком приемлемом расстоянии надо расставить наши “уши” - антенны, надо определить, как сильно флуктуирует момент детектирования сигнала в разных приемниках. Коль скоро мы будем изготавливать линейный массив - ULA (uniform linear array), расстояние между приемными элементами должно быть не меньше, чем амплитуда флуктуаций, говоря простым языком, если у нас разные приемники, антенны которых лежат рядом определяют момент прихода сигнала с разностью друг относительно друга порядка 1 миллисекунды, то расстояние между элементами менее 1.5 метров делать бессмысленно. Во-вторых, нам нужно определиться, получится ли читать состояние пинов четырех приемников при помощи Arduino Nano с достаточной скоростью и точностью или придется поискать какую-то более производительную платформу.

Теперь определимся с набором оборудования.

1.6.1. Требуемый набор оборудования

Наименование Количество Примечание
1 Модуль A3R 4  
2 Модуль A3T 1  
3 Антенна приемопередающая RT-1.332820-1 1  
4 Антенна приемная R-1.d3505-1 4  
5 Любая плата с МК, например, Arduino Nano 2  
6 Провода Dupont Male-Female или Female-Female, 15+ см 8  

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

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

1.6.2. Пингер

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

Номер/Наименование контакта на XS2 Номер/Наименование контакта на Arduino Nano
1 / GND GND
4 / Инициация передачи импульса 10
20 / VCC Vin

ОЧЕНЬ ВАЖНО! В таблице выше указано, что выход напряжения питания с платы предатчика заводится на пин Vin платы Arduino Nano - это делается только после того, как плата будет прошита и отключена от ПК!!! В противном случае, она скорее всего выйдет из строя!

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

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


#define A3T_TX_ENGAGE_PIN      (10)
#define LED_PIN                (13)
#define PING_HALF_PERIOD_MS    (2000L) 
#define TX_STROBE_DURATION_MS  (10L)

void setup() {

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  pinMode(A3T_TX_ENGAGE_PIN, OUTPUT);
  digitalWrite(A3T_TX_ENGAGE_PIN, HIGH);
}

void loop() {

    delay(PING_HALF_PERIOD_MS);
    digitalWrite(A3T_TX_ENGAGE_PIN, LOW);
    digitalWrite(LED_PIN, HIGH);
    delay(TX_STROBE_DURATION_MS);
    digitalWrite(A3T_TX_ENGAGE_PIN, HIGH);
    delay(PING_HALF_PERIOD_MS);    
    digitalWrite(LED_PIN, LOW);    

}

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

1.6.3. Приемник

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

Задание адресов приемникам при помощи установки джамперов

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

Далее подключаем стопку приемников к плате Arduino Nano согласно таблице:

Номер/Наименование контакта на XS2 Номер/Наименование контакта на Arduino Nano
1 / GND GND
6 / Строб приемника №1 2
8 / Строб приемника №2 3
10 / Строб приемника №3 4
12 / Строб приемника №4 5

У нас это получилось вот так:

Стопка из четырех приемников подключена к плате Arduino Nano
1.6.3.1. Скетч для обработки антенной решетки

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


#include "Limits.h"

#define A3R1_STATE_PIN (2)
#define A3R2_STATE_PIN (3)
#define A3R3_STATE_PIN (4)
#define A3R4_STATE_PIN (5)

#define LED_PIN (13)

const uint8_t inputPinsMasks[] = { B00100000,
                                   B00010000,
                                   B00001000,
                                   B00000100 };

const uint8_t inputPins[] = { A3R1_STATE_PIN, A3R2_STATE_PIN, A3R3_STATE_PIN, A3R4_STATE_PIN };
const int numPins = 4;

bool lastPinState[numPins];
bool pinFallen[numPins];  
unsigned long fallTime[numPins];

const unsigned long DETECTION_WINDOW = 2000;

bool is_any_pin = false;
unsigned long pin_minTime = 0;
unsigned long pin_maxTime = 0;
uint8_t fallen_pins = 0;

void checkPinTimes() {

  is_any_pin = false;
  fallen_pins = 0;

  for (int i = 0; i < numPins; i++) {
    if (pinFallen[i]) {
      fallen_pins++;

      if (!is_any_pin) {
        is_any_pin = true;
        pin_minTime = fallTime[i];
        pin_maxTime = pin_minTime;
      }
    }
  }

  if (is_any_pin) {

    for (int i = 0; i < numPins; i++) {

      if (pinFallen[i]) {
        if (fallTime[i] > pin_maxTime)
          pin_maxTime = fallTime[i];
        if (fallTime[i] < pin_minTime)
          pin_minTime = fallTime[i];
      }
    }
  }  
}

void resetAllFlags() {

  for (int i = 0; i < numPins; i++) {
    pinFallen[i] = false;
  }
}

void setup() {

  Serial.begin(9600);

  for (int i = 0; i < numPins; i++) {
    pinMode(inputPins[i], INPUT_PULLUP);

    // lastPinState[i] = digitalRead(inputPins[i]);
    lastPinState[i] = (PIND & inputPinsMasks[i]) > 0;
    pinFallen[i] = false;
    fallTime[i] = 0;
  }
}

void loop() {

  unsigned long currentTime = micros();

  uint8_t cPIND = PIND;  
  for (int i = 0; i < numPins; i++) {

    bool currentState = (cPIND & inputPinsMasks[i]) > 0;
    if (!currentState && lastPinState[i]) {
      pinFallen[i] = true;
      fallTime[i] = currentTime;
    }

    lastPinState[i] = currentState;
  }

  checkPinTimes();

  if (is_any_pin) {

    if (fallen_pins == numPins) {

      if ((pin_maxTime - pin_minTime) <= DETECTION_WINDOW) {

          /**/
          for (int i = 0; i < numPins; i++) {
            Serial.print(fallTime[i] - pin_minTime);
            Serial.print(", ");
          }
          /**/

          Serial.println();
          delay(500);
        }

      resetAllFlags();

    } else {

      if (currentTime - pin_minTime > DETECTION_WINDOW * 100) {

        resetAllFlags();
        delay(100);
      }
    }
  }
}

Забегая вперед, отметим, что в скетче пришлось отказаться от стандартных функций digitalRead и перейти к прямой работе с регистрами для ускорения. Это некоторым образом делает скетч менее гибким.

1.6.4. Эксперимент по определению амплитуды разброса времени прихода

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

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

Экспериментальная установка в нашем случае выглядит вот так:

Ведро не обязательно должно быть синим =)

Итак:

Если все собрано правильно, то в окне утилиты ‘Serial Monitor’ мы сможем увидеть приходящие раз в 4 секунды строчки, содержащие по 4 числа через запятую. Скетч нормализует времена прихода - вычитает наименьшее из каждой группы. Достаточно будет набрать несколько десятков строк.

У нас получился такой набор
Формат CSV (Comma-separated values), нормализованные времена прихода сигнала в микросекундах
#id,receiver_4,receiver_3,receiver_2,receiver1
1,0,140,56,200
2,56,236,0,56
3,0,84,24,172
4,0,28,28,180
5,0,132,132,132
6,0,172,0,172
7,0,248,160,160
8,0,228,168,24
9,0,112,52,140
10,56,316,0,168
11,0,356,52,84
12,0,204,112,0
13,0,168,80,108
14,0,272,212,212
15,0,32,0,32
16,0,264,28,112
17,0,116,52,52
18,28,168,140,0
19,0,116,56,56
20,0,92,0,32
21,0,144,28,84
22,0,252,80,192
23,0,28,60,28
24,208,244,0,208
25,60,0,28,148
26,84,0,24,112
27,132,280,188,0
28,0,136,108,168
29,168,136,0,52
30,80,136,0,136
31,136,136,0,52
32,88,204,172,0
33,0,140,228,196
34,108,108,196,0
35,28,172,140,0
36,28,116,0,56
37,120,120,0,0
38,80,228,0,164
39,164,164,0,52
40,0,104,188,188
41,0,260,108,80
42,52,152,52,0
43,0,56,28,56
44,108,0,136,136
45,28,268,120,0
46,160,248,0,188
47,0,224,76,164
48,0,280,128,128
49,0,28,56,152
50,28,84,0,204
51,0,172,52,84
52,0,224,80,192
53,80,224,0,192
54,0,140,28,140
55,0,136,52,196
56,24,168,140,0
57,88,56,28,0
58,0,92,0,56
59,0,28,184,56
60,28,84,84,0
61,0,172,80,52
62,28,148,0,88
63,80,108,140,0
64,28,152,0,64
65,28,0,60,0
66,56,96,28,0
67,172,52,0,52
68,0,224,164,52
69,0,28,88,56
70,136,108,0,168
71,0,32,0,32
72,108,228,52,0
73,0,32,0,60
74,0,276,132,244
75,84,0,260,52
76,28,88,0,28
77,0,116,28,84
78,0,340,160,132
79,0,108,108,108
80,0,164,52,164
81,28,204,0,84
82,28,120,28,0
83,0,84,56,116
84,0,104,160,192
85,28,228,0,168
86,0,232,0,144
87,0,228,76,76
88,108,0,192,192
89,0,168,112,200
90,28,112,0,144
91,56,196,0,196
92,80,0,52,120
93,56,300,84,0
94,0,336,216,132
95,0,144,28,112
96,0,148,0,176
97,112,172,28,0
98,56,0,84,116
99,0,0,0,64
100,0,164,224,80
101,0,120,0,88
102,28,60,28,0
103,108,108,0,108
104,0,80,164,164
105,112,172,0,56
106,0,28,60,28
107,28,168,200,0
108,52,0,84,52
109,24,0,112,232
110,0,260,108,52
111,0,204,140,28
112,0,348,0,168
113,0,292,60,172
114,0,220,80,220
115,28,260,0,168
116,0,132,104,164
117,116,52,0,84
118,0,216,216,132
119,0,176,0,116
120,28,144,84,0
121,52,228,0,136
122,0,172,52,108
123,84,144,0,52
124,0,152,0,0
125,0,164,196,80
126,80,228,0,164
127,0,140,140,28
128,28,176,0,84
129,56,0,28,116
130,28,28,60,0
131,0,80,80,228
132,0,88,28,184
133,60,120,0,0
134,0,120,0,32
135,120,28,28,0
136,80,196,0,164
137,0,216,184,156
138,52,224,0,196
139,0,164,80,256
140,0,80,80,80
141,84,24,0,84
142,0,176,84,56
143,108,140,80,0
144,160,248,216,0
145,32,156,0,0
146,28,208,56,0
147,104,256,104,0
148,0,280,80,192
149,28,264,84,0
150,136,0,80,256
151,0,260,112,80
152,80,232,0,80
153,56,196,0,228
154,60,180,28,0
155,0,264,84,28
156,164,344,108,0
157,0,60,0,148
158,0,60,0,148
159,28,172,264,0
160,132,0,188,220
161,56,236,24,0
162,164,108,0,164
163,64,184,32,0
164,0,164,164,52
165,0,80,136,136
166,0,228,80,140
167,56,112,0,200
168,0,140,80,52
169,28,348,0,196
170,28,60,236,0
171,136,196,0,80
172,0,32,0,156
173,0,84,84,28
174,56,0,112,204
175,28,288,0,196
176,0,132,132,164
177,28,116,0,116
178,56,152,24,0
179,0,168,80,168
180,0,52,52,180
181,156,224,0,156
182,0,112,56,172
183,84,176,0,28
184,0,116,84,28
185,0,84,28,116
186,60,0,60,28
187,0,132,164,132
188,60,120,0,60
189,0,280,132,188
190,52,172,112,0
191,88,0,28,28

Для наглядности нанесем эти времена на график:

Большая часть значений не превышает 300 мкс

Из этого графика мы видим, что в основном, времена прихода колеблются относительно друг друга в пределах 300-350 микросекунд. Для скорости звука ~1500 м/с это соответствует примерно 0.5 метра.

Очень полезно и легко запомнить, что за одну миллисекунду звук в воде распространяется примерно на 1.5 метра.

Точность не фантастическая, но с этим вполне можно работать.

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

1.6.5. Антенная решетка

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

Простейшая конструкция для размещения четырех приемных антенн через метр друг от друга

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

Давайте прикинем плавучесть всей рамы. Для этого сначала взвесим ее: у нас получилось 1,5 кг. Теперь нужно прикинуть объем вытесняемой воды по нижней границе - вес у нас по верхней границе, объем - по нижней, если масса воды полученного объема с некоторым запасом превышает измеренный вес, то все в порядке: конструкция вполне будет держаться на воде. Вычислять будем очень просто, т.к. нам нужен минимальный объем, то мы просто посчитаем объем трубы, без учета фитингов - они увеличивают объем.
Итак, у нас труба диаметром 25 мм, значит площадь сечения $πr^2 = 3.1415*0.0125^2=0.000490859 \space м^2$. Длина всей использованной трубы 8 м, умножаем одно на другое и получаем объем вытесняемой воды: $0.000490859 * 8 = 0.003926875 \space м^3$. Масса этого объема воды, с учетом плотности в $1000 \space кг/м^3$ составит 3.9 кг. А измеренный вес всей конструкции всего 1.5 кг, значит у нас есть 3.9-1.5=2.4 кг избыточной плавучести.

Без доработок, кабелей приемных антенн хватит чтобы свесить антенны вниз примерно на 15-20 см.

Отметки делаются при помощи изоленты

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

Запаса по длине кабеля практически нет

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

1.6.6. Эксперимент в бассейне

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

Для начала определимся с тем, где “лево” и где “право”: слева находится антенна №1 а справа - антенна №4:

Порядок расположения антенн в решетке

Как минимум, должны быть такие расположения

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

Вот наша схема эксперимента:

№1 .. №4 - положения источника сигнала, R1 .. R4 - положения элементов приемной антенной решетки

Для каждого взаимного расположения антенной решетки и источника рекомендуется набрать 150-200 измерений.

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

Полезно контролировать эксперимент - наблюдать, что данные, во-первых, приходят, а во-вторых, хотя бы в общих чертах понимать, что они адекватные. Например, если источник строго слева, то сначала сигнал должен прийти на антенну №1, затем на №2 и так далее, а наш скетч передает времена прихода в обратном порядке, и мы ожидаем увидеть четыре подряд убывающие числа, например 1936, 1284, 724, 0, . Крайне рекомендуем перед проведением эксперимента представить себе, какие примерно данные вы ожидаете получить. Это хорошая практика не только для этого конкретного эксперимента, но и для любого другого, и вообще хорошая практика по жизни.

Держим руку на пульсе

Мы получили наборы данных для пяти различных взаимных расположения приемной решетки и источника сигнала: слева, между слева и спереди, спереди, между спереди и справа, справа. Тепература воды в бассейне во время проведения эксперимента была 21.6 °С.

Вот эти данные, так же - в формате CSV (comma-separated values):

Эксперимент №1 - источник строго слева
# Нормализованные времена прихода в микросекундах receiver_4,receiver_3,receiver_2,receiver_1
1936, 1284, 724, 0
1964, 1428, 680, 0
1924, 1424, 696, 0
1884, 1228, 728, 0
1852, 1344, 652, 0
1816, 1336, 784, 0
1936, 1228, 832, 0
1936, 1368, 724, 0
1880, 1432, 604, 0
1892, 1332, 800, 0
1980, 1392, 856, 0
1864, 1416, 808, 0
1852, 1380, 652, 0
1912, 1376, 628, 0
1924, 1476, 756, 0
1988, 1364, 756, 0
1932, 1308, 808, 0
1888, 1444, 828, 0
1972, 1348, 628, 0
1880, 1408, 628, 0
1868, 1392, 808, 0
1972, 1204, 784, 0
1872, 1400, 732, 0
1960, 1488, 652, 0
1868, 1420, 776, 0
1992, 1400, 732, 0
1928, 1392, 784, 0
1936, 1308, 784, 0
1928, 1340, 808, 0
1944, 1232, 724, 0
1908, 1344, 704, 0
1948, 1300, 576, 0
1968, 1372, 628, 0
1912, 1316, 680, 0
1936, 1224, 836, 0
1912, 1380, 656, 0
1988, 1392, 748, 0
1980, 1448, 832, 0
1852, 1344, 652, 0
1912, 1228, 724, 0
1976, 1204, 680, 0
1940, 1256, 724, 0
1976, 1528, 836, 0
1964, 1280, 808, 0
1932, 1424, 696, 0
1956, 1420, 776, 0
1968, 1340, 676, 0
1936, 1404, 596, 0
1964, 1368, 732, 0
1956, 1388, 832, 0
1968, 1404, 628, 0
1992, 1196, 776, 0
1976, 1288, 680, 0
1968, 1524, 912, 0
1872, 1336, 784, 0
1976, 1444, 884, 0
1904, 1340, 756, 0
1932, 1432, 676, 0
1980, 1444, 836, 0
1984, 1416, 780, 0
1928, 1424, 808, 0
1948, 1476, 888, 0
1900, 1420, 728, 0
1936, 1220, 832, 0
1968, 1404, 628, 0
1992, 1196, 776, 0
1976, 1288, 680, 0
1968, 1524, 912, 0
1872, 1336, 784, 0
1976, 1444, 884, 0
1904, 1340, 756, 0
1932, 1432, 676, 0
1980, 1444, 836, 0
1984, 1416, 780, 0
1928, 1424, 808, 0
1948, 1476, 888, 0
1900, 1420, 728, 0
1936, 1220, 832, 0
2000, 1196, 756, 0
1972, 1384, 604, 0
1924, 1336, 804, 0
1896, 1416, 808, 0
1972, 1528, 912, 0
1988, 1424, 732, 0
1920, 1332, 856, 0
1968, 1496, 576, 0
1840, 1420, 756, 0

Эксперимент №2 - источник между направлениями строго слева и напротив
# Нормализованные времена прихода в микросекундах receiver_4,receiver_3,receiver_2,receiver_1
1816, 1372, 728, 0
1640, 1852, 784, 0
1680, 1856, 732, 0
1844, 1904, 732, 0
1948, 1556, 784, 0
1760, 1792, 732, 0
1772, 1036, 724, 0
1752, 1068, 652, 0
1796, 1112, 832, 0
1760, 1232, 724, 0
1840, 1812, 388, 0
1872, 1100, 628, 0
1800, 1268, 1072, 0
1920, 1148, 704, 0
1680, 1208, 732, 0
1888, 1740, 544, 0
1640, 1816, 884, 0
1744, 1124, 732, 0
1672, 1228, 724, 0
1844, 1872, 704, 0
1976, 1384, 964, 0
1924, 1392, 776, 0
1960, 1216, 884, 0
1860, 1416, 912, 0
1844, 1340, 700, 0
1720, 1808, 884, 0
1812, 1664, 936, 0
1864, 1680, 568, 0
1764, 1856, 680, 0
1860, 1268, 652, 0
1836, 1864, 860, 0
1820, 1224, 836, 0
1808, 1336, 884, 0
1812, 1716, 884, 0
1824, 1224, 756, 0
1716, 1068, 756, 0
1796, 1668, 756, 0
1804, 1776, 884, 0
1748, 1308, 884, 0
1828, 1860, 912, 0
1880, 1344, 676, 0
1768, 1296, 624, 0
1904, 1340, 724, 0
1804, 1864, 912, 0
1892, 1324, 964, 0
1628, 1424, 836, 0
1736, 1440, 880, 0
1644, 1024, 884, 0
1908, 1224, 808, 0
1820, 1792, 596, 0
1768, 1356, 856, 0
1712, 1204, 704, 0
1904, 1256, 832, 0
1748, 1272, 884, 0
1860, 1892, 500, 0
1992, 1308, 836, 0
1852, 1940, 656, 0
1740, 1236, 704, 0
1920, 1352, 544, 0
1772, 1148, 732, 0
1968, 1260, 424, 0
1856, 1200, 756, 0

Эксперимент №3 - источник напротив
# Нормализованные времена прихода в микросекундах receiver_4,receiver_3,receiver_2,receiver_1
132, 0, 300, 360
104, 0, 272, 480
300, 0, 180, 388
28, 84, 0, 204
188, 0, 128, 480
0, 56, 228, 376
28, 112, 0, 112
260, 0, 260, 260
464, 28, 0, 168
688, 0, 132, 296
604, 0, 156, 156
428, 0, 28, 224
708, 0, 184, 376
640, 0, 260, 404
676, 0, 352, 184
540, 0, 208, 236
636, 0, 80, 252
560, 0, 128, 352
692, 0, 184, 184
496, 0, 52, 52
712, 0, 180, 208
652, 0, 208, 292
788, 0, 56, 256
616, 0, 156, 380
696, 0, 104, 188
736, 0, 212, 380
108, 0, 108, 168
472, 112, 56, 0
664, 0, 104, 104
172, 0, 84, 56
616, 0, 380, 208
604, 0, 80, 192
56, 24, 24, 0
612, 0, 108, 164
628, 0, 76, 272
268, 0, 184, 356
232, 0, 232, 232
528, 0, 184, 348
660, 0, 108, 300
604, 0, 160, 192
688, 0, 336, 364
612, 52, 0, 192
868, 360, 0, 360
628, 0, 104, 272
764, 0, 208, 344
664, 0, 24, 308
812, 0, 56, 192
660, 28, 0, 360
728, 0, 344, 400
564, 0, 156, 240
552, 0, 52, 220
576, 104, 0, 280
780, 0, 260, 424
572, 0, 104, 300
556, 0, 28, 196
604, 0, 160, 104
660, 0, 156, 184
644, 0, 80, 108
676, 0, 236, 264
660, 0, 80, 328
700, 0, 80, 220
680, 0, 180, 264
544, 0, 156, 212
244, 0, 188, 244
328, 0, 132, 416
312, 0, 104, 132
184, 0, 308, 248
248, 52, 0, 280
216, 0, 248, 80
192, 164, 0, 312
56, 0, 28, 296
76, 0, 272, 332
104, 0, 280, 280
136, 0, 104, 104
388, 52, 0, 388
84, 0, 28, 328
116, 28, 0, 84
164, 0, 80, 224
280, 0, 164, 220
312, 0, 136, 104
364, 0, 336, 452
352, 0, 320, 292
132, 0, 160, 220
272, 0, 104, 332
60, 0, 176, 144
296, 0, 156, 296
312, 0, 164, 104
84, 0, 116, 116
248, 0, 80, 220
104, 0, 104, 196
140, 0, 252, 340
276, 0, 80, 336
316, 0, 232, 348
168, 0, 112, 376
84, 28, 0, 232
244, 0, 160, 272
112, 0, 252, 252
52, 0, 192, 340
348, 0, 208, 408
188, 0, 300, 300
180, 0, 212, 300
220, 0, 52, 280
300, 0, 132, 300
84, 28, 0, 264
28, 0, 56, 144
272, 0, 216, 272
344, 0, 260, 344
80, 0, 136, 164
200, 0, 56, 140
288, 0, 256, 316
240, 0, 156, 328
168, 0, 112, 316
112, 0, 56, 172
264, 0, 208, 324
56, 56, 0, 264
0, 56, 0, 116
52, 0, 192, 340
56, 24, 0, 232
188, 0, 104, 248
192, 80, 0, 252
84, 0, 112, 260
372, 0, 312, 340
192, 0, 52, 224
256, 0, 112, 196
104, 0, 308, 216
324, 0, 156, 384
276, 0, 192, 276
276, 104, 0, 244
236, 0, 180, 296
168, 0, 112, 200
188, 0, 104, 336
80, 0, 164, 196
324, 0, 240, 356
160, 0, 76, 308
364, 0, 132, 216
200, 0, 60, 232
184, 0, 184, 304
304, 0, 80, 332
284, 0, 84, 224
104, 0, 76, 168
104, 0, 244, 304
296, 0, 240, 296
180, 0, 236, 356
332, 0, 80, 300
148, 0, 24, 116
188, 0, 104, 308
24, 0, 136, 228
120, 0, 28, 296
372, 0, 260, 372
232, 0, 0, 112
244, 0, 212, 212
52, 52, 0, 260
180, 0, 208, 328
292, 0, 32, 172
220, 0, 160, 104
216, 0, 160, 244
264, 0, 264, 264
0, 24, 84, 56
284, 0, 80, 192
344, 0, 372, 404
224, 0, 104, 104
112, 0, 0, 112
292, 0, 292, 472
368, 0, 284, 368
0, 56, 84, 320
308, 0, 188, 188
328, 0, 156, 240
240, 0, 180, 208
224, 52, 0, 344
168, 0, 28, 140
132, 0, 248, 188
192, 0, 160, 160
56, 28, 176, 0
132, 0, 104, 252
332, 0, 104, 392
156, 0, 156, 188
132, 0, 308, 188
160, 0, 104, 160
128, 128, 0, 220
304, 56, 0, 364

Эксперимент №4 - источник между направлениями напротив и строго справа
# Нормализованные времена прихода в микросекундах receiver_4,receiver_3,receiver_2,receiver_1
0, 420, 1228, 1644
0, 464, 1108, 1968
0, 364, 1060, 1680
0, 416, 1196, 1764
0, 496, 1024, 1620
0, 496, 1108, 1968
0, 128, 744, 1424
0, 604, 688, 1724
0, 364, 916, 1544
0, 652, 876, 1736
0, 104, 828, 1720
0, 292, 984, 1580
0, 388, 864, 1456
0, 596, 1208, 1924
0, 724, 864, 1460
76, 0, 748, 1308
0, 292, 1012, 1756
0, 260, 984, 1868
0, 652, 928, 1492
0, 544, 1240, 1924
312, 0, 532, 1572
0, 184, 936, 1528
0, 180, 1072, 1640
0, 516, 968, 1852
0, 680, 820, 1496
0, 156, 1048, 1676
0, 576, 1272, 1920
0, 232, 848, 1468
0, 0, 720, 1608
0, 232, 1096, 1392
0, 544, 1216, 1960
0, 340, 868, 1552
0, 56, 692, 1552
0, 132, 1024, 1560
0, 232, 904, 1524
0, 544, 1296, 1952
0, 240, 904, 1620
0, 336, 980, 1512
0, 260, 740, 1416
0, 396, 952, 1664
0, 156, 904, 1620
0, 80, 776, 1696
0, 368, 948, 1428
0, 312, 864, 1492
0, 104, 692, 1460
0, 240, 740, 1512
0, 236, 768, 1504
0, 644, 1232, 1948
180, 0, 624, 1248
0, 312, 924, 1604
180, 0, 568, 1284
0, 232, 848, 1380
0, 292, 624, 1340
0, 652, 1040, 1992
164, 0, 524, 1416
0, 104, 632, 1668
0, 184, 744, 1868
444, 0, 668, 1468
288, 0, 708, 1240
344, 0, 480, 1256
0, 336, 756, 1940
0, 312, 760, 1652
0, 492, 1272, 1928
0, 260, 704, 1564
360, 0, 756, 1256
236, 0, 540, 1076
0, 104, 884, 1276
260, 0, 564, 1280
340, 0, 732, 1324
344, 0, 648, 1148
0, 732, 1340, 1848
188, 0, 328, 976
0, 628, 1128, 1724
0, 0, 644, 1292
216, 0, 632, 1492
336, 0, 756, 1436
0, 676, 1208, 1948
316, 0, 540, 1284
516, 0, 856, 1328
388, 0, 756, 1168
264, 0, 596, 1156
156, 0, 708, 980
416, 0, 584, 1296
388, 0, 868, 1192
268, 0, 684, 1160
0, 756, 1280, 1788
180, 0, 520, 1344
140, 0, 552, 968
0, 628, 1124, 1868
388, 0, 776, 1372
232, 0, 600, 1160
156, 0, 572, 924
260, 0, 540, 1076
156, 0, 496, 1084
0, 748, 1504, 1708
420, 0, 700, 1352
256, 0, 620, 1036
308, 0, 648, 1120
0, 652, 1372, 1732
260, 0, 508, 1428
208, 0, 768, 1212
0, 620, 1292, 1948
0, 680, 1316, 1648
236, 0, 768, 1092
344, 0, 648, 1092
0, 728, 1228, 1824
0, 680, 1316, 1824
156, 0, 412, 1120
264, 0, 680, 1036
232, 0, 540, 988
208, 0, 572, 1076
372, 0, 896, 1192
260, 0, 756, 1116
440, 0, 888, 1360
260, 0, 624, 1068
0, 724, 1368, 1848
184, 0, 652, 1044
284, 0, 568, 1220
288, 0, 928, 1280

Эксперимент №5 - источник строго справа
# Нормализованные времена прихода в микросекундах receiver_4,receiver_3,receiver_2,receiver_1
0, 704, 1508, 1956
0, 524, 1308, 1924
0, 652, 1156, 1776
0, 728, 1284, 1908
0, 724, 1532, 1952
0, 704, 1488, 1840
0, 672, 1480, 1960
0, 704, 1340, 1876
0, 680, 1516, 1956
0, 544, 1492, 1904
0, 724, 1448, 1920
0, 728, 1392, 1988
0, 680, 1372, 1908
0, 548, 1384, 1884
0, 620, 1456, 1936
0, 676, 1432, 1992
0, 656, 1548, 1932
0, 676, 1564, 1924
0, 524, 1276, 1924
0, 652, 1544, 1988
0, 704, 1484, 1984
0, 680, 1428, 1936
0, 780, 1368, 1956
0, 620, 1568, 1984
0, 704, 1484, 1896
0, 676, 1480, 1840
0, 652, 1320, 1940
0, 596, 1320, 1944
0, 704, 1232, 1944
0, 628, 1464, 1996
0, 696, 1480, 1952
0, 680, 1516, 1988
0, 776, 1528, 1920
0, 572, 1292, 1948
0, 656, 1520, 1960
0, 696, 1560, 1924
0, 576, 1128, 1992
0, 884, 1556, 1908
0, 748, 1364, 1836
0, 704, 1512, 1984
0, 652, 1488, 1960
0, 672, 1204, 1948
0, 732, 1480, 1956
0, 524, 1076, 1852
0, 836, 1584, 1912
0, 728, 1456, 1984
0, 652, 1456, 1876
0, 808, 1476, 1920
0, 696, 1396, 1992
0, 756, 1392, 1900
0, 756, 1508, 1980
0, 696, 1424, 1952
0, 576, 1348, 1740
0, 732, 1092, 1980
0, 828, 1528, 1912
0, 780, 1364, 1988
0, 752, 1420, 1928
0, 600, 1268, 1800
0, 756, 1480, 1952
0, 776, 1392, 1840
0, 784, 1504, 1980
0, 784, 1532, 1952
0, 780, 1280, 1992
0, 680, 1400, 1964
0, 780, 1480, 1980
0, 628, 1292, 1740
0, 756, 1424, 1988
0, 628, 1184, 1956
0, 672, 1316, 1968
0, 628, 1320, 1944
0, 704, 1264, 2000
0, 756, 1456, 1956
0, 680, 1544, 1988

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

1.6.7. Обработка результатов эксперимента

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

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

Иллюстрация падения плоского фронта волны на два приемника

На картинке выше фронт волны падает на два приемника под углом $\alpha$, при этом между приходом на первый приемник (слева) и приходом на второй (справа) есть задержка $\Delta t$ Если скорость распространения $V$ а расстояние между приемниками $\Delta X$, то угол $\alpha$ можно определить из соотношения:

\[\frac{\Delta t * V}{\Delta X} = cos(\alpha)\]

Косинус - это отношение прилежащего катета к гипотенузе, гипотенуза в нашем случае это $\Delta X$, а прилежащий катет $\Delta t * V$.

Правило КО МНЕ:
Очень легко запомнить что такое косинус КОсинус - отношение (КО МНЕ) прилежашего катета к гипотенузе. Значит синус - отношение противолежащего катета к гипотенузе, КОтангенс - отношение (КО МНЕ) прилежащего катета к противолежащему, А тангенс - отношение противолежащего к прилежащему.

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

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

К определению угла прихода сигнала на линейную антенную решетку

На схеме выше показана система координат с центром в первом приемнике, ось X направлена как обычно вправо, а вот по оси Y у нас откладывается время, умноженное на скорость распространения волны.

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

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

Но, всегда ведь есть какое-то “но”, правда?

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

В 1929 году Эдвин Хаббл именно таким образом и сформулировал свой знаменитый закон, проведя линию по совокупности измерений.

График из оригинальной работы Хаббла 1929 года

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

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

Хорошая новость состоит в том, что тут нет ничего сложного: провести линию, значит получить ее уравнение. Уравнение линии простое и имеет общий вид $y=kx+b$. То есть требуется определить коэффициенты $k$ и $b$ и, забегая вперед скажем, что коэффициент $b$ нам в общем-то не нужен.

А коэффициент $k$ определяется по такой формуле:

\[k = \frac {n \sum{x_i y_i} - \sum{x_i} \sum{y_i} } {n \sum {x^2_i} - (\sum {x_i})^2}\]

$x_i$ - Это координаты наших приемников: 0 - для первого, 1 - для второго, коль скоро мы условились, что расстояния между ними равны 1 метру. $y_i$ - это измеренные времена прихода, умноженные на скорость звука в воде.

Теперь еще один очень важный момент: коэффициент $k$ - это тангенс угла наклона линии, относительно оси X. Взгляните еще раз на схему выше:

\[tg \phi = \frac{\Delta t * V}{\Delta X}\]

А мы помним, что

\[\frac{\Delta t * V}{\Delta X} = cos(\alpha)\]

Получается интересная вещь, что:

\[tg \phi = cos \alpha = \frac{\Delta t * V}{\Delta X}\]

Отсюда мы легко можем посчитать угол $\alpha$ - угол прихода сигнала. Еще раз, вот вся последовательность измерений и вычислений:

  1. Определяем времена прихода на все элементы антенной решетки
  2. При помощи линейной аппроксимации находим коэффициент $k$ уравнения прямой - это по определению и есть тангенс угла наклона этой прямой
  3. Угол прихода сигнала определяем как арккосинус от $k$

Все эти данные затруднительно представить при помощи графика в Excel или в чем-то похожем, поэтому придется прибегнуть к Matlab, точнее к его свободному аналогу - GNU Octave.

Данные для обработки удобно сохранить в отдельные файлы “как есть” - то есть в формате CSV. Мы сохраним их под именами data1.csv, data2.csv, data3.csv, data4.csv и data5.csv.

Для их обработки мы подготовили следующий скрипт:


clc;
clear all;
close all;

% Параметры обработки
Num = 5;  % Номер набора данных (1-5)

% Загрузка данных
data_1 = csvread('data1.csv');
data_2 = csvread('data2.csv');
data_3 = csvread('data3.csv');
data_4 = csvread('data4.csv');
data_5 = csvread('data5.csv');

actual_angles = [180, 135, 90, 45, 0];  % Фактические углы для каждого набора

% Выбор данных для обработки
if (Num == 1) src_data = data_1;
elseif (Num == 2) src_data = data_2;
elseif (Num == 3) src_data = data_3;
elseif (Num == 4) src_data = data_4;
elseif (Num == 5) src_data = data_5;
endif

% Физические параметры
v = 1503.6;  % Скорость звука в воде, м/с
t_scale = 1 / 1000000;  % Масштаб времени (мкс в секунды)

% Координаты приемников антенной решетки (ULA)
ula4_xs = [3 2 1 0];
ula4_ys = [0 0 0 0];

% Создание одного окна с двумя subplot
figure('Position', [100, 100, 1200, 600]);  % Увеличенный размер окна

%% Первый график: измерения и аппроксимация
subplot(1, 2, 1);  % 1 строка, 2 столбца, позиция 1
axis equal
hold on
grid on

% Предварительные вычисления для линейной регрессии
x_sum = sum(ula4_xs);
x2_sum = sum(ula4_xs .^ 2);
x_sum2 = x_sum ^ 2;
rec_num = length(ula4_xs);

% Инициализация массивов
k = zeros(length(src_data), 1);  % Коэффициенты наклона
b = zeros(length(src_data), 1);  % Свободные члены
alpha = zeros(length(src_data), 1);  % Углы прихода

% Обработка каждого измерения
for n = 1:length(src_data)
    % Преобразование временных задержек в расстояния
    ys = src_data(n, :) .* t_scale .* v;

    % Проверка данных на корректность
    if ~all(isfinite(ys))
        warning('Обнаружены некорректные данные в строке %d. Пропускаю.', n);
        continue;
    end

    % Построение графиков измерений
    if n == 1
        plot(ula4_xs, ys, 'b.', 'DisplayName', 'Измерения V·t', 'MarkerSize', 4);
    else
        plot(ula4_xs, ys, 'b.', 'HandleVisibility', 'off', 'MarkerSize', 4);
    end

    % Вычисление коэффициентов прямой (метод наименьших квадратов)
    y_sum = sum(ys);
    xy_sum = sum(ula4_xs .* ys);

    denominator = (rec_num * x2_sum - x_sum2);
    if denominator == 0
        warning('Вырожденная система в строке %d. Пропускаю.', n);
        continue;
    end

    k(n) = (rec_num * xy_sum - x_sum * y_sum) / denominator;
    b(n) = (y_sum - k(n) * x_sum) / rec_num;

    % Построение линии аппроксимации
    x_range = [0, 3];
    y_range = k(n) * x_range + b(n);

    if n == 1
        line(x_range, y_range, 'Color', 'red', 'LineWidth', 0.5, 'DisplayName', 'Линейная аппроксимация');
    else
        line(x_range, y_range, 'Color', 'red', 'LineWidth', 0.5, 'HandleVisibility', 'off');
    end

    % Вычисление угла прихода через арккосинус
    k_bound = max(min(k(n), 1), -1);  % Ограничение для области определения acos
    alpha(n) = acos(-k_bound);
end

% Отображение позиций приемников
plot(ula4_xs, ula4_ys, 'go', 'MarkerSize', 8, 'MarkerFaceColor', 'g', 'DisplayName', 'Элементы антенны');

% Настройка первого графика
tstr = sprintf("Линейная аппроксимация tgφ=cosα\nФактический угол: %d°, выборка: %d",...
               actual_angles(Num), length(src_data));
title(tstr, "fontsize", 14);
xlabel('X, m', "fontsize", 14);
ylabel('V·t, m', "fontsize", 14);

lh = legend('show');
set(lh, "fontsize", 12);

%% Второй график: гистограмма углов
subplot(1, 2, 2);  % 1 строка, 2 столбца, позиция 2

alpha_deg = rad2deg(alpha);  % Преобразование радиан в градусы

% Статистика углов
mean_alpha = mean(alpha_deg);
std_alpha = std(alpha_deg);
max_alpha = max(alpha_deg);
min_alpha = min(alpha_deg);

% Построение гистограммы
nbins = 20;
[counts, bins] = hist(alpha_deg, nbins);
hist(alpha_deg, nbins, 'DisplayName', 'α, °');
colormap(summer());

hold on;
y_limits = ylim;

% Линии статистик на гистограмме
plot([mean_alpha, mean_alpha], y_limits, 'r-', 'LineWidth', 2,...
     'DisplayName', sprintf('Среднее = %.1f°', mean_alpha));

plot([mean_alpha - std_alpha, mean_alpha - std_alpha], y_limits, 'g--',...
     'LineWidth', 1.5, 'DisplayName', sprintf('±1 СКО (%.1f°)', std_alpha));
plot([mean_alpha + std_alpha, mean_alpha + std_alpha], y_limits, 'g--',...
     'LineWidth', 1.5, 'HandleVisibility', 'off');

% Настройка второго графика
llh = legend('show');
set(llh, "fontsize", 12);

tstr = sprintf("Определение угла прихода\nФактический угол: %d°, выборка: %d",...
               actual_angles(Num), length(src_data));
title(tstr, "fontsize", 14);
xlabel('Угол α, °', "fontsize", 14);
ylabel('Частота', "fontsize", 14);

% Вывод статистики в консоль
fprintf('\n=== СТАТИСТИКА УГЛОВ ===\n');
fprintf('Среднее: %.2f°\n', mean_alpha);
fprintf('СКО: %.2f°\n', std_alpha);
fprintf('Минимум: %.2f°\n', min_alpha);
fprintf('Максимум: %.2f°\n', max_alpha);
fprintf('Размах: %.2f°\n', max_alpha - min_alpha);

Напомним пару моментов:

Теперь давайте посмотрим на результаты.

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

Итак, для угла 180° - источник строго слева от антенной решетки:

Фактический угол 180°
Фактический угол 135°
Фактический угол 90°
Фактический угол 45°
Фактический угол 0°

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

Мы видим, что в среднем СКО (среднеквадратичное отклонение) определения угла прихода составляет порядка 6°. Среднее значение по выборке соответствует фактическому углу во всех экспериментах, кроме эксперимента №2 (135°). Особенно хороший результат получился при 90° и при 45°.

Как можно улучшить эту систему? Во-первых, обеспечить фиксированное положение антенных элементов (приемников), нарастив им кабеля и усовершенствовав раму. А во-вторых, было бы интересно посмотреть на результат в более щадящих условиях, например в небольшом естественном водоеме.

Предлагаем продвинутому пользователю самому разобраться вот в каком вопросе: мы сделали допущение, что в наших экспериментах фронт мы считаем плоским. Но в действительности считать его таковым можно только в случае углов 180° и 0°, когда источник находится на оси антенной решетки. А если посмотреть на график с измерениями для угла 90°, то невооруженным глазом видно, что вместо линии лучше бы подошла дуга окружности. Да, это скорее задача с двумя звездочками для начинающих, но успешно решив ее, можно совершенно заслуженно поставить самому себе плюсик в карму.

Ну и давайте подытожим:

Поздравим и похвалим сами себя с завершением одного из самых сложных проектов этого руководства - вы великолепны!

1.7. (Планируется) Проект 5 - Определение положения ответчика методом виртуальной длинной базы

1.7.1. (Планируется) Требуемый набор оборудования

1.8. (Планируется) Проект 6 - Длиннобазисная навигационная система

1.8.1. (Планируется)Требуемый набор оборудования

1.8.2. (Планируется)Навигационный буй-приемник

2. (Планируется) A3TC и A3RC

3. (Планируется) A3T2 и A3R2

4. (Планируется)A3AM

К содержанию