Принимаем стандарт IEEE802.15.4-2003 по технологии SDR(Software Defined Radio)

от автора

IEEE802.15.4 — стандарт для беспроводных персональных сетей с низким уровнем мощности сигнала в нелицензированных диапазонах частот.
Он определяет физический уровень и MAC уровень доступа к среде.
В этой статье рассматривается физический уровень, версия 2003 года и OQPSK модуляция.

Сначала немного теории.
Стандарт рассчитан на устройства с низким потреблением и низкой стоимостью. Поэтому в нем выбран метод модуляции OQPSK имеющий малый пик-фактор (отношение пиковой мощности к средней) и допустима высокая нестабильность передатчика 40ppm.
Диапазон(который будем принимать) 2400-2483.5МГц.
Это нелицензируемый диапазон ISM(Industrial, Scientific, Medical) и в нем предусмотрены каналы с 11 по 26 шириной по 2МГц.
Для совместного использования спектра с другими устройствами, например Wi-Fi, и помехоустойчивости, применяется метод расширения спектра DSSS(direct-sequence spread spectrum).
Скорость передачи данных в канале составляет 250КБит/с. Биты объединены в символы по четыре и каждый символ передается псевдо шумовой последовательностью из 32х отсчетов.
Итого получаем частоту дискретизации 2МГц. Для определения начала сигнала, и нужд синхронизации, передается преамбула из восьми символов «0».

Теперь практика.
Частота дискретизации 2МГц минимальна. На практике (при приеме) её увеличивают. Это удобно сделать вдвое, т.е 4Мгц.
Для частотной, временной и фазовой синхронизации необходимо принять преамбулу. Классический метод — сравнение принятого сигнала с задержанным.
Преамбула состоит из восьми нолей и сравнивая принятый сигнал, и задержанный на время передачи символа 16мкс, можно определить рассинхронизацию.
Можно но не всю. При нестабильности в 40ppm разность фаз может превысить 180гр. Здесь не приводиться расчета, но при такой нестабильности сравнивать можно только с задержанным сигналом не более чем на 5мкс. И здесь наступает расплата за дешевизну — «low cost» дорожает.
Есть разные методы решить эту проблему. Выбранный метод — двойная кросс-корреляция.
Т.к. сравнивать можно одинаковые сигналы, а менее чем через 16мкс сигнал не повторяется, то для сравнения применим местный, синтезированный сигнал, соответствующий символу «0». В этом методе принятый сигнал делится на небольшие части менее 5мкс и сравнивается с ожидаемым локальным.
Данное сравнение даст нам отличие по частоте (угол между векторами) от местного сигнала для каждой части, но не от частоты передачи.
Но вторая кросс-корреляция уже полученных смещений между собой и будет нужной оценкой.
Вроде все долго и запутанно, но в итоге функция довольно простая:

complex ieee802_15_4::double_correlator(const complex *chip_) {     for(int j = 0; j < num_segment; ++j){         int n = j * len_segment;         seg_real[j] = 0.0f;         seg_imag[j] = 0.0f;         for(int i = n; i < n + len_segment; ++i){             seg_real[j] += chip_[i].real() * local_zz_real[i] + chip_[i].imag() * local_zz_imag[i];             seg_imag[j] += chip_[i].imag() * local_zz_real[i] - chip_[i].real() * local_zz_imag[i];         }     }     float sum_real = 0.0f;     float sum_imag = 0.0f;     for(int i = 1; i < num_segment; ++i){         int j = i - 1;         sum_real += seg_real[i] * seg_real[j] + seg_imag[i] * seg_imag[j];         sum_imag += seg_imag[i] * seg_real[j] - seg_real[i] * seg_imag[j];     }      return {sum_real, sum_imag};  } 

и самая требовательная к производительности.

И получаем наши восемь символов:

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

После преамбулы ожидается два символа 0x07 и 0x0A описанные в стандарте как SDF(start-of-frame delimiter) или разделение начала кадра. К ним уже можно применить наше вычисленное смещение по частоте, а сравнив первый символ с локальным(ожидаемым), получим и отклонение по фазе:

Здесь зеленая линия — принятый сигнал, красная — ожидаемый(синтезированный или локальный). На горизонтальной оси номера отсчетов. До 64-го отсчета символ 0x07 и он синхронизирован по частоте. После 64-го отсчета символ 0x0A. Он уже синхронизирован по фазе. Хорошо видно почти идеальное совпадение, особенно с учетом того, что решение о принятом бите принимается по расположению отсчета с большей амплитудой относительно центральной оси. Напомним — работаем с передискретизацией в два раза на приеме и дискретизация в два раза при передаче. При принятии решения три отсчета отбрасываются.

Остается синхронизация по времени.
Для синхронизации по времени применён интерполятор Фарроу по схеме — 4 point, 3rrd order Hermite, x-form. Звучит угрожающе но выглядит в коде не так сложно:

complex ieee802_15_4::interpolator(const complex &data_, const float &mu_) {     // 4-point, 3rd-order Hermite (x-form)     delay_data_3 = delay_data_2;     delay_data_2 = delay_data_1;     delay_data_1 = data_;     complex c0 = delay_data_2;     complex c1 = 0.5f * (delay_data_1 - delay_data_3);     complex c2 = delay_data_3 - 2.5f * delay_data_2 + 2.0f * delay_data_1 - 0.5f * data_;     complex c3 = 0.5f * (data_ - delay_data_3) + 1.5f * (delay_data_2 - delay_data_1);     x1 = mu_;     x2 = x1 * x1;     x3 = x2 * x1;     complex x = c3 * x3 + c2 * x2 + c1 * x1 + c0;     complex out = {i_delay_2, x.imag()};     i_delay_2 = i_delay_1;     i_delay_1 = x.real();      return out;  } 

Здесь нужно вычислить задержку mu_.
Сделаем это сравнивая синхронизированный символ 0x0A с локальным путем корреляции.
По точкам корреляционной кривой определим искомое mu_ методом рано-поздно:

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

Можно декодировать фрейм, но только короткий. Если 5 байт типа “acknowledgment” принимались уверенно, то более длинный “data” разваливался в конце.
Начальной синхронизации оказалось недостаточно. Увеличивать точность не хотелось.
Компьютер старенький, уже 7 лет, производительность на исходе, уже и так много написанно, лень …
Поэтому следующий метод без названия. На просторах интернета не нашел что-то подобное, но “ничто не ново под луной”.
Суть метода проста. Раз первые символы принимаются замечательно(см. картинку выше), то можно вычислить фазовую ошибку и компенсировать в следующем символе. И так до конца.
И вот созвездие OQPSK:

А здесь принят и подтвержден (в стандарте проверка целостности CRC16) довольно слабый сигнал:

Вычисление соотношения сигна — шум пока нет.

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

Собственно весь UI целиком:

Сам проект можно посмотреть здесь: https://github.com/Oleg-Malyutin/SDR_ieee802.15.4_PHY

В дальнейших планах передатчик (и это гораздо проще).
Спасибо за внимание.


ссылка на оригинал статьи https://habr.com/ru/articles/915758/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *