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

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

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

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

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

Эта статья является продолжением предыдущей статьи Гидроакустические «кубики» - где я рассказывал о создаваемом нами наборе разных гидроакустических шилдов, из которых, по нашей задумке, можно будет сделать макет практически любой гидроакустической системы. Я постарался представить материал так, чтобы без лишней надобности не отсылать глубокоуважаемого читателя к предыдущей статье.

0. Intro

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

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

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

Эти устройства спроектированы так, что могут объединяться в стек до 12-ти штук - именно на столько рассчитана шина, примерно так:

12 штук набрать никак не получается - почти все, что собрали сразу разослали по учебным заведениям
12 штук набрать никак не получается - почти все, что собрали сразу разослали по учебным заведениям

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

1. Что будем делать

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

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

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

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

Наименование

Кол-во

1

Модуль A³R

4

2

Модуль A³T

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.

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

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 миллисекунд к земле, инициируя тем самым передачу сигнала.

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

Удобно крепить макеты на картонку или кусок МДФ
Удобно крепить макеты на картонку или кусок МДФ

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
Стопка из четырех приемников подключена к плате Arduino Nano

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] = (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 и перейти к прямой работе с регистрами для ускорения. Это некоторым образом делает скетч менее гибким.

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

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

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

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

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

Итак:

  • плата Arduino передатчика прошита и отключена от ПК

  • плата Arduino приемника прошита и подключена к ПК

  • в среде Arduino IDE открыта утилита 'Serial Monitor' или запущено любое другое терминальное приложения для получения данных с последовательного порта

  • на стопку приемников подано питание

  • на передатчик подано питание

Если все собрано правильно, то в окне утилиты 'Serial Monitor' в Arduino IDE мы сможем увидеть приходящие раз в 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 мкс

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

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

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

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

Для пуристов сразу проясним: она не фазированная. Мы просто разнесли отдельные приемные элементы на определенное расстояние.

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

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

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

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

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

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

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

Запас. Да, его нет.
Запас. Да, его нет.

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

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

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

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

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

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

  • "слева": передатчик находится ровно слева на линии, на которой лежат антенны

  • "cпереди": передатчик находится на линии, перпендикулярной линии антенны

  • "справа": передатчик находится ровно справа на линии, на которой лежат антенны

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

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

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

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

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

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

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

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

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

\frac{\Delta t*V}{\Delta X}=cos\alpha

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

Правило КО МНЕ

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

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

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

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

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

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

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

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

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

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

График из работы Э. П. Хаббла 1929 года
График из работы Э. П. Хаббла 1929 года

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

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

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

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

k=\frac{n\sum{x_iy_i}-\sum{x_i}\sum{y_i}}{n\sum{x_i^2}-(\sum{x_i})^2}

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

Теперь еще один очень важный момент: коэффициент 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}

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

  1. Определяем времена прихода на все элементы антенной решетки

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

  3. Угол прихода сигнала определяем как арккосинус от k

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

Данные для обработки удобно сохранить в отдельные файлы "как есть" - то есть в формате CSV. Мы сохраним их под именами data1.csvdata2.csvdata3.csvdata4.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);

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

  • углы мы отсчитываем против часовой стрелки от горизонтали.

  • у нас есть 5 наборов данных, полученных для углов 180, 135, 90, 45 и 0°.

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

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

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

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

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

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

Как можно улучшить эту систему? 

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

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

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

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

  • мы оценили, насколько флуктуируют определяемые времена прихода сигнала в разных приемниках

  • на основе этих данных мы сделали угломерную систему на основе 4-х элементной антенной решетки

  • сделали простейшее оптимизационное решение на основе линейной аппроксимации

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

  • оценили статистические свойства полученного результата

8. Outro

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

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

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

Ваши, до глубины души

@AlekDikarev

@StDmitriev

@andrey_9999a

@vital792

@Creathor

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