Перейти к содержимому
Возможно ли изменить рабочий диапазон работы ELRS?
01
июля
2025

Возможно ли изменить рабочий диапазон работы ELRS?

 

Возможно ли изменить рабочий диапазон работы канала приемо-передачи elsr, например, для работы на базовой частоте 750Мгц?

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

Адрес репозитория: https://github.com/ExpressLRS/ExpressLRS.git - исходный код протокола.
Нас интересует файл FHSS.cpp. Он находится в папке \src\lib\FHSS.
Здесь мы имеем дело с кодом, который реализует механизм Frequency Hopping Spread Spectrum (FHSS) для радиомодуля в проекте ELRS. Код предназначен для работы с разными типами радиомодулей (SX127x, LR1121, SX128x) и разными регулирующими доменами (разные частотные диапазоны и правила).

Исходный код FHSS

#include "FHSS.h"
#include "logging.h"
#include "options.h"
#include <string.h>

#if defined(RADIO_SX127X) || defined(RADIO_LR1121)

#if defined(RADIO_LR1121)
#include "LR1121Driver.h"
#else
#include "SX127xDriver.h"
#endif

const fhss_config_t domains[] = {
    {"AU915",  FREQ_HZ_TO_REG_VAL(915500000), FREQ_HZ_TO_REG_VAL(926900000), 20, 921000000},
    {"FCC915", FREQ_HZ_TO_REG_VAL(903500000), FREQ_HZ_TO_REG_VAL(926900000), 40, 915000000},
    {"EU868",  FREQ_HZ_TO_REG_VAL(865275000), FREQ_HZ_TO_REG_VAL(869575000), 13, 868000000},
    {"IN866",  FREQ_HZ_TO_REG_VAL(865375000), FREQ_HZ_TO_REG_VAL(866950000), 4, 866000000},
    {"AU433",  FREQ_HZ_TO_REG_VAL(433420000), FREQ_HZ_TO_REG_VAL(434420000), 3, 434000000},
    {"EU433",  FREQ_HZ_TO_REG_VAL(433100000), FREQ_HZ_TO_REG_VAL(434450000), 3, 434000000},
    {"US433",  FREQ_HZ_TO_REG_VAL(433250000), FREQ_HZ_TO_REG_VAL(438000000), 8, 434000000},
    {"US433W",  FREQ_HZ_TO_REG_VAL(423500000), FREQ_HZ_TO_REG_VAL(438000000), 20, 434000000},
};

#if defined(RADIO_LR1121)
const fhss_config_t domainsDualBand[] = {
    {"ISM2G4", FREQ_HZ_TO_REG_VAL(2400400000), FREQ_HZ_TO_REG_VAL(2479400000), 80, 2440000000}
};
#endif

#elif defined(RADIO_SX128X)
#include "SX1280Driver.h"

const fhss_config_t domains[] = {
    {
    #if defined(Regulatory_Domain_EU_CE_2400)
        "CE_LBT",
    #elif defined(Regulatory_Domain_ISM_2400)
        "ISM2G4",
    #endif
    FREQ_HZ_TO_REG_VAL(2400400000), FREQ_HZ_TO_REG_VAL(2479400000), 80, 2440000000}
};
#endif

// Наша таблица FHSS частот
const fhss_config_t *FHSSconfig;
const fhss_config_t *FHSSconfigDualBand;

// Фактическая последовательность скачков
uint8_t FHSSsequence[FHSS_SEQUENCE_LEN];
uint8_t FHSSsequence_DualBand[FHSS_SEQUENCE_LEN];

// Текущая позиция в последовательности
uint8_t volatile FHSSptr;

// Канал для синхронизации
uint_fast8_t sync_channel;
uint_fast8_t sync_channel_DualBand;

// Коррекция частоты
int32_t FreqCorrection;
int32_t FreqCorrection_2;

// Шаг частоты
uint32_t freq_spread;
uint32_t freq_spread_DualBand;

// Переменные для двухдиапазонных радио
bool FHSSusePrimaryFreqBand = true;
bool FHSSuseDualBand = false;

uint16_t primaryBandCount;
uint16_t secondaryBandCount;

void FHSSrandomiseFHSSsequence(const uint32_t seed)
{
    FHSSconfig = &domains[firmwareOptions.domain];
    sync_channel = FHSSconfig->freq_count / 2;
    freq_spread = (FHSSconfig->freq_stop - FHSSconfig->freq_start) * FREQ_SPREAD_SCALE / (FHSSconfig->freq_count - 1);
    primaryBandCount = (FHSS_SEQUENCE_LEN / FHSSconfig->freq_count) * FHSSconfig->freq_count;

    DBGLN("Setting %s Mode", FHSSconfig->domain);
    DBGLN("Number of FHSS frequencies = %u", FHSSconfig->freq_count);
    DBGLN("Sync channel = %u", sync_channel);

    FHSSrandomiseFHSSsequenceBuild(seed, FHSSconfig->freq_count, sync_channel, FHSSsequence);

#if defined(RADIO_LR1121)
    FHSSconfigDualBand = &domainsDualBand[0];
    sync_channel_DualBand = FHSSconfigDualBand->freq_count / 2;
    freq_spread_DualBand = (FHSSconfigDualBand->freq_stop - FHSSconfigDualBand->freq_start) * FREQ_SPREAD_SCALE / (FHSSconfigDualBand->freq_count - 1);
    secondaryBandCount = (FHSS_SEQUENCE_LEN / FHSSconfigDualBand->freq_count) * FHSSconfigDualBand->freq_count;

    DBGLN("Setting Dual Band %s Mode", FHSSconfigDualBand->domain);
    DBGLN("Number of FHSS frequencies = %u", FHSSconfigDualBand->freq_count);
    DBGLN("Sync channel Dual Band = %u", sync_channel_DualBand);

    FHSSusePrimaryFreqBand = false;
    FHSSrandomiseFHSSsequenceBuild(seed, FHSSconfigDualBand->freq_count, sync_channel_DualBand, FHSSsequence_DualBand);
    FHSSusePrimaryFreqBand = true;
#endif
}

/**
Требования к последовательности:
1. Синхроканал каждые N скачков
2. Без повторяющихся каналов
3. Равномерное распределение
4. Псевдослучайность
*/
void FHSSrandomiseFHSSsequenceBuild(const uint32_t seed, uint32_t freqCount, uint_fast8_t syncChannel, uint8_t *inSequence)
{
    FHSSptr = 0;
    rngSeed(seed);

    // Инициализация массива последовательности
    for (uint16_t i = 0; i < FHSSgetSequenceCount(); i++)
    {
        if (i % freqCount == 0) {
            inSequence[i] = syncChannel;
        } else if (i % freqCount == syncChannel) {
            inSequence[i] = 0;
        } else {
            inSequence[i] = i % freqCount;
        }
    }

    // Перемешивание последовательности
    for (uint16_t i = 0; i < FHSSgetSequenceCount(); i++)
    {
        if (i % freqCount != 0)
        {
            uint8_t offset = (i / freqCount) * freqCount;
            uint8_t rand = rngN(freqCount - 1) + 1;

            uint8_t temp = inSequence[i];
            inSequence[i] = inSequence[offset+rand];
            inSequence[offset+rand] = temp;
        }
    }

    // Отладочный вывод последовательности
    for (uint16_t i=0; i < FHSSgetSequenceCount(); i++)
    {
        DBG("%u ",inSequence[i]);
        if (i % 10 == 9)
            DBGCR;
    }
    DBGCR;
}

bool isDomain868()
{
    return strcmp(FHSSconfig->domain, "EU868") == 0;
}

Пояснение реализации FHSS

1. Регуляторные домены

Массив domains содержит конфигурации для разных регионов:

Пример:
{"EU868", FREQ_HZ_TO_REG_VAL(865275000), FREQ_HZ_TO_REG_VAL(869575000), 13, 868000000}

ПолеОписание
domain Название домена (например, "EU868")
freq_start Начальная частота диапазона 865275000
freq_stop Конечная частота диапазона 869575000
freq_count Количество каналов 13
sync_freq Центральная частота синхронизации 868000000

2. Ключевые функции

ФункцияНазначение
FHSSrandomiseFHSSsequence() Основная инициализация FHSS
FHSSrandomiseFHSSsequenceBuild() Генерация псевдослучайной последовательности
isDomain868() Проверка европейского диапазона

3. Алгоритм генерации последовательности

  1. Инициализация блоками:
    • Каждый N-й элемент = синхроканал
    • Остальные позиции заполняются последовательно (0,1,2...)
  2. Перемешивание:
    • Для каждого элемента (кроме синхро) в блоке
    • Обмен со случайной позицией в том же блоке

Добавление нового диапазона (750 МГц)

Техническая реализация

#if defined(RADIO_SX127X) || defined(RADIO_LR1121)
const fhss_config_t domains[] = {
    // ... существующие диапазоны
    {"EU750",  
     FREQ_HZ_TO_REG_VAL(740000000),
     FREQ_HZ_TO_REG_VAL(760000000),
     20, 
     750000000}
};
#endif

Проблемы и ограничения

КатегорияПроблемыРешение
Аппаратные
  • Поддержка радиочипом (SX1280 не поддерживает)
  • Проблемы с КСВ антенного тракта
  • Конструкция антенны (~20 см)
  • Проверка спецификаций чипа
  • Тесты с анализатором спектра
Регуляторные
  • Лицензирование (LTE Band 12/13/14)
  • Ограничения мощности
  • Сертификация оборудования
  • Юридическая экспертиза
Программные
  • Совместимость с существующим кодом
  • Автовыбор диапазона
  • Реализация через #ifdef
  • Геолокационные ограничения

Рекомендации

  • Использовать только для специализированных проектов
  • Реализовать как экспериментальный режим
  • Обязательная проверка на легальность в целевом регионе

Раздел: Как сделать.., Конспекты, Незаданные вопросы

Возможно ли изменить рабочий диапазон работы ELRS?