惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AWS News Blog
AWS News Blog
V
Vulnerabilities – Threatpost
D
Darknet – Hacking Tools, Hacker News & Cyber Security
量子位
博客园 - 叶小钗
AI
AI
T
Tor Project blog
Forbes - Security
Forbes - Security
W
WeLiveSecurity
博客园_首页
爱范儿
爱范儿
J
Java Code Geeks
B
Blog
G
GRAHAM CLULEY
aimingoo的专栏
aimingoo的专栏
Cloudbric
Cloudbric
C
CXSECURITY Database RSS Feed - CXSecurity.com
TaoSecurity Blog
TaoSecurity Blog
L
LINUX DO - 热门话题
阮一峰的网络日志
阮一峰的网络日志
有赞技术团队
有赞技术团队
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Simon Willison's Weblog
Simon Willison's Weblog
云风的 BLOG
云风的 BLOG
Google DeepMind News
Google DeepMind News
H
Help Net Security
博客园 - 三生石上(FineUI控件)
C
Cisco Blogs
C
Cybersecurity and Infrastructure Security Agency CISA
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
P
Palo Alto Networks Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Commits to openclaw:main
Recent Commits to openclaw:main
博客园 - 司徒正美
The Last Watchdog
The Last Watchdog
Blog — PlanetScale
Blog — PlanetScale
T
The Blog of Author Tim Ferriss
S
Secure Thoughts
Spread Privacy
Spread Privacy
F
Fortinet All Blogs
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
H
Hackread – Cybersecurity News, Data Breaches, AI and More
A
About on SuperTechFans
Security Latest
Security Latest
Webroot Blog
Webroot Blog
Scott Helme
Scott Helme
Hugging Face - Blog
Hugging Face - Blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Передача данных по лазерному лучу (BPSK)
aabzel · 2026-05-07 · via Все публикации подряд на Хабре

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

Постановка задачи:

Наладить беспроводную передачу бинарных данных по лазерному лучу в реальном времени. Битовая скорость 25 бит в секунду. В качестве аппаратуры трансивера задействовать электронную плату с микроконтроллером STM32F407VE.

Данные передавать BPSK модуляцией (QAM-2). Частота несущей должна быть 250 Hz. Частота дискретизации - 1kHz (Длительность семпла 1 ms). Битовая частота BPSK 25 bit/s. Длительность одного чирпа 40ms (40 семплов). Сигнал принимать фотодиодом в связке с операционным усилителем (микросхема OPT101). Все вычисления по приёму и цифровой обработке данных выполнять на уровне прошивки микроконтроллера STM32F407VE. Надо принять при помощи ADC1 семплы с выхода фотодатчика, который подключен к пину PA3. В прошивке надо декодировать BPSK модуляцию. Запрограммировать программный Costas Loop внутри прошивки. Поток принятых битов отображать в GPIO. Печатать биты в виде последовательности hex чисел.

Теория

Все модуляции (ASK, OOK, BPSK, FSK, 256-QAM, CSS, GFSK, MSK) можно отнести к интерфейсам физического уровня модели OSI-7, так как модуляции поясняют как именно передаются биты в физической среде. BPSK тоже можно рассматривать как интерфейс физического уровня.

Какие есть параметры у BPSK сигнала?

Параметр

Единица измерения

Значение

1

несущая частота

Hz

250

2

битовая скорость

bit/s

25

3

амплитуда несущей

PCM

2000

4

длительность одного чипа

секунды

40ms

5*

Частота дискретизации

Hz

1000

6

порядок бит при упаковке байта внутри BPSK сигнала

младшим битом вперёд / старшим битом вперед

MSB

7*

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

bit

12

Вот так выглядит BPSK сигнал в частотной области. Br - это битовая скорость.

Спектр BPSK сигнала

Спектр BPSK сигнала

При понижении Br битовой скорости BPSK вырождается в синус. Поэтому при уменьшении битовой скорости ширина сигнала сужается. При повышении битовой скорости BPSK спектр расширяется.

chip (чип) - это минимальный фрагмент BPSK сигнала, где фаза несущей частоты не меняется. Фактический в BPSK чип это один бит данных.

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

Реализация

Что надо из оборудования?

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

Количество

Пояснение

Цена

Лазерный модуль KY-008

2

Для отправки сигнала

200

Электронная плата  JZ-F407VET6

2

Для обработки данных

1200

OPT101 Monolithic Photodiode and Single-Supply Transimpedance Amplifier

2

Фотодиод с операционным усилителем для приема сигнала

2300

Элемент солнечной батареи (optional)

2

для приема сигнала

?

Прежде всего Вам потребуется лазерный модуль KY-008. Надо купить сразу несколько экземпляров, так как попадаются бракованные экземпляры.

Фотоприемником может быть как отдельный Фотодиод BPW21R, 420..675нм с отдельным операционным усилителем. Так и полностью интегрированный компонент OPT101, содержащий как фотодиод, так и операционный усилитель.

Параметры связи

Попробуем передавать 25 бит в секунду. На один бит пусть приходиться один чирп. Частота несущей пусть будет 250 Hz. По есть один чирп - это 10 периодов несущей.

Передатчик

С передачей данных по лазеру всё достаточно просто. Лазерный передатчик - это просто микроконтроллер, который генерирует PWM сигнал. Микроконтроллеры STM32 позволяет инвертировать фазу этого PWM.

bool timer_polarity_set(uint8_t num, TimerOutChannel_t channel, TimerPolarity_t polarity) {
    bool res = false;
    TimerInfo_t* Info = TimerGetInfo(num);
    if(Info ){
        TimerRegCCER_t CCER;
        CCER.dword = Info->TIMx->CCER;

        switch(channel){
            case TIMER_OUT_CHANNEL_0:{
                res = false;
            } break;
            case TIMER_OUT_CHANNEL_1:{
                CCER.CC1P = TimerPolarityToStmPolarity(polarity);
            } break;
            case TIMER_OUT_CHANNEL_2:{
                CCER.CC2P = TimerPolarityToStmPolarity(polarity);
            } break;
            case TIMER_OUT_CHANNEL_3:{
                CCER.CC3P = TimerPolarityToStmPolarity(polarity);
            } break;
            case TIMER_OUT_CHANNEL_4:{
                CCER.CC4P = TimerPolarityToStmPolarity(polarity);
            } break;
            case TIMER_OUT_CHANNEL_5:{
                res = false;
            } break;
            default : res = false; break;
        }
        Info->TIMx->CCER=CCER.dword ;
    }
    return res;
}

Получается, что можно делать сдвиг фазы на 180 градусов. Таким образом, можно практически аппаратно и бесплатно на лету генерировать на пине цифровой BPSK сигнал. Далее подключает к этому пину лазерный модуль KY-008 и получаем модулированный BPSK лазерный луч, передающий данные в мировое пространство.

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

Приемник

Прием BPSK сигнала - это большая и нетривиальная задача.

Фаза 1: Захват семплов

Если неcущая у нас 250 Hz, то частота дискретизации по теореме Котельникова должна быть как минимум 500 Hz. Я пока поставлю для надежности частоту дискретизации равную 1k Hz. Про получение потока ADC отсчетов у меня есть отдельный текст: Потоковая запись ADC семплов на STM32. Это не так просто как кажется на первый взгляд. Надо задействовать DMA, прерывания и пр.

Фаза 2: Фильтрация постоянного смещения
После измерения на ADC отсчёты всегда приходят положительные 0.....4095. Как на лету отсеивать постоянную составляющую сигнала для последующей ЦОС обработки? Для этой цели, есть вот такой цифровой фильтр.

в коде это выглядит вот так

bool dc_cut_filter_proc_sample(uint8_t num, 
                               const int32_t x_n, 
                               int32_t* const y_n) {
    bool res = false;
    DcCutFilterHandle_t *Node = DcCutFilterGetNode(num);
    if (Node) {
        if (y_n) {
            int32_t e_n = (Node->numerator * Node->a_n_1)/Node->denominator;
            int32_t a_n = x_n + e_n;
            *y_n = a_n - Node->a_n_1;
            res = true;
            Node->a_n_1 = a_n;
        }
    }
    return res;
}

фильтр в самом деле работает и исключает постоянное смещение.

Фаза 3: Снятие сигнала с несущей частоты

Надо настроить гетеродин, который будет выдавать два сигнала: sin и cos на частоте несущей. В нашем случае на частоте 250 Hz. При этом, так как мы принимаем PWM, то и сигнал гетеродина надо генерировать тоже в виде PWM. Вот так.

Первое, что происходит с переменным сигналом после ADC это его перемножение через смеситель (перемножитель) на сигналы квадратурного гетеродина. Фаза этого гетеродина будет позже регулироваться алгоритмом Costas Loop.

Чтобы исходный сигнал снять с несущей его надо пропустить через квадратурный смеситель. Внутри квадратурного смесителя работает локальный генератор: гетеродин. Частота гетеродина равна частоте несущей. То есть 250 Hz. Период гетеродина соответственно 4 ms. При этом длительность семпла у нас 1ms. Получается, что на один период гетеродина приходится всего 4 семпла. Это значит, что фазу гетеродина мы сможем регулировать только в 4х позициях: 0, 90, 180, 270 градусов. Это упрощает задачу регулирования фазы гетеродина. Об этом позже.

Фаза 4: Отсев двойной частоты

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

Надо как-то ликвидировать высокую частоту на выходе смесителя. Для этого сигнал надо пропустить через фильтр нижних частот. Это надо сделать так, чтобы было поменьше вычислений. Самым простым фильтром является оконный интегратор. По сути это однородный FIR фильтр, у которого все коэффициенты равны единице. Получается фильтр с усилением. Зато это относительно просто вычислять в условиях исполнения на микроконтроллере. Но можно еще больше упростить однородный фильтр, если на каждом шаге не суммировать все элементы, а просто добавлять первый и вычитать последний элементы из сдвигового регистра z^{-N}.

Скользящий интегратор

Скользящий интегратор

Фаза 5: Определение смещения фазы гетеродина

На выходе фильтров IQ получается два целых числа, которые образуют комплексное число. Надо вычислить аргумент этого комплексного числа и его минимальное отклонение от оси X. Это можно определить при помощи функции арктангенса. Если на выходе I/Q после фильтра нижних частот получился комплексный ноль, то как определить ошибку по фазе? Ведь нулевой вектор может быть направлен в любую сторону. В этом случае можно просто считать, что ошибка по фазе равна нулю.

/*
            Q
            ^
    --------|++++++++
    --------|++++++++
  __--------|++++++++_______\I
    ++++++++|--------       /
    ++++++++|-----*--
    ++++++++|--------
 */
inline float calc_carrier_phase_err_rad(float i_val, float q_val) {
    float carr_phase_err_rad = 0.0f;
    if(0.0f < i_val) {
        carr_phase_err_rad = atan2f(q_val, i_val); // -pi/2......  pi/2
    } else {
        carr_phase_err_rad = atan2f(-q_val, -i_val);// -pi/2......  pi/2
    }
#ifdef HAS_BPSK_DEBUG
    LOG_PARN(SDR, "Phase,%f+j(%f),Err:%7.6f Rad",i_val,q_val, carr_phase_err_rad);
#endif
    return carr_phase_err_rad;
}

Удивительно то, что когда я заменил atan2f на извлечение значений фаз из предварительно рассчитанных LookUp таблиц, то обработка стала только медленнее.

float calc_carrier_phase_err_lut_rad(const int32_t i_val, const int32_t q_val) {
    float phase_err_rad = 0.0f;
    if(0<=i_val) {
        if(0<=q_val) {
            phase_err_rad = phaseErrRadLUT_iqPos[i_val][q_val];
        }else{
            phase_err_rad = phaseErrRadLUT_iPosQNeg[i_val][-q_val];
        }
    }else{
        if(0<=q_val){
            phase_err_rad = phaseErrRadLUT_iNegQpos[-i_val][q_val];
        }else{
            phase_err_rad = phaseErrRadLUT_iNegQneg[-i_val][-q_val];
        }
    }
#ifdef HAS_BPSK_DEBUG
    LOG_PARN(QUAD_MIX_4FS, "Phase,%f+j(%f),Err:%7.6f Rad",i_val,q_val, phase_err_rad);
#endif
    return phase_err_rad;
}

Фаза 6 Регулирование фазы гетеродина.

Фаза гетеродина величина инертная. Меняется только при изменении расстояния между передатчиком и приемником. Поэтому фаза не может меняться мгновенно. Менять фазу надо непрерывно и медленно. Отлаживать алгоритм можно вообще на статической прохардкоженной фазе. Фазу гетеродина можно регулировать PID регулятором. PID регуляторы это не только про регулирование температуры нагревателя или частоты вращения мотора. PID регулятор вполне может применятся в SDR обработке сигналов. Интегральная часть регулятора завязана на размер сдвигового регистра в фильтре нижних частот. Надо назначать интегральный коэффициент равным 1/M, где M-длинна сдвигового регистра в скользящем сумматоре, который образует ФНЧ.

Фаза 7 Прореживание сигнала

Как только PID регулятор выйдет на корректную фазу, начнется уверенный прием битов. Данные будут в I компоненте комплексного числа. Q будет равна нулю. Однако эти биты по-прежнему на частоте дискретизации (1kHz). Чтобы выделать логические биты (25 bit/s) надо пропустить сигнал I_Filt через компаратор и дециматор. Дециматор прореживает поток семплов. Из 40 семплов одного знака оставляет только один. Из битов далее формируются байты. Дециматор легко реализовать на основе конечного автомата из трёх состояний.

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

Фаза 8 Прием битов информации.

Принятые биты можно отображать на отдельном GPIO пине. Сами биты лучше кодировать самосинхронизирующимся кодом. Например манчестерским кодом.

Поэтому на принимающей стороне надо декодировать манчестерский код. Найти первую последовательность 11 или 00 и начать декодировать реальные биты .

Достоинства BPSK модуляции
++Относительная простота декодирования. Достаточно настроить Costas Loop и можно смело принимать поток битов.

Недостатки BPSK модуляции

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

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

--BPSK модуляция не показывается начало и конец пакета с данными. Не показывает начало и конец отдельных байтов. Всё, что мы получаем это поток нулей и единиц. Пакетная синхронизация это задача более высоких уровней обработки данных. Можно конечно добавить отдельный пин для индикации того факта, что Costas loop вышел в режим стабилизации, однако это потребует дополнительных вычислений, которые негативно повлияют на производительность прошивки.

Какие параметры в BPSK приемнике?

При написании программы обработки BPSK модулированного сигнала вам придется конфигурировать множество параметров. В своей установке я выбрал вот такие параметры.

Параметр

Какое значение ставить

Единицы измерения

Несущая частота

250

Hz

Частота дискретизации ADC

1000

Hz

Форма сигнала гетеродина

PWM

форма сигнала

Битовая скорость

25

bit/s

Параметр ФВЧ для отсева DC смещения (0 ....1)

0.95

--

Порядок FIR фильтра

26

семплов

Конфиги PID регулятора

I=1/FIRordef (0.001)

безразмерный

Как отлаживать прием данных по BPSK?
1) IQ отображать на DAC. Таким образом можно анализировать сигнальное созвездие буквально осциллографом в режиме реального времени отрисовывая фигуры Лисажу.

Название провода

Что отображать

GPIO

MCU pin

DAC_OUT1

I

PA4

29

DAC_OUT2

Q

PA5

30

2) Весть тракт декодирования, всю SDR обработку можно отладить на LapTop PC внутри консольного Win приложения, написанного на том же самом языке программирования, что и микроконтроллерная прошивка, то есть на языке программирования Си.

3) Прием битов можно просматривать при помощи логического анализатора. Принятые биты показывать на GPIO. Буквально двумя пинами: RxData и RxClock.

Одним пином я показываю биты (data), а вторым пином я показываю границу битов (clock). На каждом перепаде тактирования clock выдвигается новый бит принятых данных в data (режим DDR).

4) Можно соединить передатчик и приемник проводной перемычкой, полностью минуя оптическую часть. Буквально от PWM к ADC. Это позволить отлаживать приём отбрасывая возможные проблемы в среде передачи данных.

Объединив заземление передатчика и приемника, можно на логическом анализаторе DS Logic сверять переданные и отправленные биты. Как можно заметить, данные в самом деле передаются и корректно принимаются. Можно заметить корреляцию между переданными битами и принятыми битами.

Чтобы сильно не нагружать прошивку я отображаю принятые биты прямо на GPIO. Буквально двумя пинами: data и clock. Одним пином я показываю биты, а вторым пином я показываю границу битов. На каждом перепаде тактирования clock выдвигается новый бит данных в data.

Оценка производительности

SDR обработка BPSK семплов это весьма трудоемкая процедура для микроконтроллера. Эксперименты проводил на микроконтроллере с ядром ARM Cortex-M4 (STM32F407VET6). Модульный тест показывает, что в среднем на обработку одного ADC семпла уходит 732 us.

Это значит, что на ARM Cortex-M4 168MHz частота дискретизации обработки ADC семплов не может превышать 1366 Hz. Иначе прошивка просто захлебнётся от наплыва необработанных отсчетов от АЦП.

Эксперимент с реальным лазерным лучом.

Трансляцию данных я произвел на основе двух плат JZ-F407VET6. Одна была передатчиком, вторая приемником.

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

Сам фотодиод OPT101 был установлен на макетной плате.

По лазеру я циклически передавал байт 0xF0 в манчестерском коде. То есть в BPSK модулятор передатчика периодически поступал 2х байтовый массив 0xaa55. На принимающей стороне мне удалось принять 4 байта подряд!

Достоинства передачи данных по лазерному лучу
++Это акустически бесшумный способ передачи информации.
++Отсутствуют сигнал в радио спектре. Трудно подслушать.
++При неподвижном передатчике и приемнике фаза особо не меняется. И передатчик и приемник статичные.
++BPSK сигнал легко аппаратно модулировать обыкновенным PWM на любом микроконтроллере, никак при этом не нагружая микроконтроллер.

Идеи проектов лазерной связи

--Передача данных между космическими спутниками.
--Военно-полевая связь. Можно сделать бинокль с передачей речи по лазерному лучу.
--Интернет между домами. Вместо провисающих проводов.
--Датчики качества воздуха. По нарушению связи можно делать выводы по взвешенным частицам пыли в объёмах воздуха.
--Можно сделать ГСН, которая будет ориентироваться только на фото сигналы строго определенного кода, который передается по BPSK лазерным лучом.
--Передача и прием данных через оптоволокно. Лазером можно светить в оптоволокно. Тогда можно прокладывать данные по извилистым маршрутам.
--Каждый светодиодный светильник уличные фонари можно сделать передатчиками бинарных данных. То есть помимо свечения, светильник может транслировать на высокой несущей ещё и точное время, свою геолокацию, номер этажа, почтовый индекс, адрес дома и прочее. Мобильные телефоны (или автомобили) могут принимать эти данные фронтальным фотодатчиком и анализировать метаданные.

Итоги и результаты

Удалось научиться декодировать BPSK сигнал буквально из потока ADC семплов в реальном времени.

По лазерному лучу мне удалось передать и принять подряд 32 бит информации на битовой скорости 25 bps на расстояние 5 см!

В качестве дальнейшего развития этого способа надо делать квадратурный смеситель полностью аппаратным. Либо перекладывать задачу снятия сигнала с несущей на FPGA, либо искать специализированный ASIC для декодирования BPSK сигнала.

Надеюсь этот текст вдохновит кого-нибудь сделать лазерный BPSK приёмник на более производительных микроконтроллерах или даже на FPGA и добиться более высоких битовых скоростей приема данных.

Словарь

Сокращение

Расшифровка

PID

Proportional-Integral-Derivative

ADC

Analog-to-Digital Converter

ФВЧ

Фильтр Высоких Частот

ФНЧ

Фильтр Нижних Частот

ГСН

Головка СамоНаведения

SDR

Software-Defined Radio

NCO

Numerically controlled oscillator

PWM

Pulse Width Modulation

BPSK

Binary Phase Shift Keying

Ссылки

Название

URL

Управление фазой аппаратного PWM сигнала на STM32

https://habr.com/ru/articles/1023940/

Потоковая запись ADC семплов на STM32

https://habr.com/ru/articles/1025090/

Цифровая обработка сигналов, Ричард Лайонс, 2006, изд. Бином.

https://www.bsuir.by/m/12_100229_1_85526.pdf

BPW21R, Фотодиод 420..675нм

https://www.chipdip.ru/product/bpw21r-fotodiod-420-675nm-vishay-403152527?utm_source=direct&utm_medium=cpc&utm_campaign=Y_dinamicheskaya_max_conv&utm_content=text1_ya&utm_term=---autotargeting&position_type=dynamic_places&etext=&ybaip=1

Самодельный фазовый лазерный дальномер @iliasam

https://habr.com/ru/articles/213749/

Оптический реверс-инжиниринг лазерного дальномера @AndreyWinter

https://habr.com/ru/articles/1022284/

Устройство слежения за движущимся источником света @avrfun

https://habr.com/ru/articles/120086/

Декодирование BPSK Модуляции из Звука (или передача данных по воздуху)

https://habr.com/ru/articles/848068/

KY-008 3pin 650nm Red Laser Transmitter Dot Diode Copper Head Module GOHJMY

https://aliexpress.ru/item/1005008353967710.html?spm=a2g2w.orderlist.rcmdprod.14.4c234aa6HuXctt&mixer_rcmd_bucket_id=backtestMarchReleases&pdp_trigger_item_id=0_1005008671169336&ru_algo_pv_id=a82164-2a6053-767aa6-c48fc3-1776196800&scenario=appOrderListRecommend&shpMethod=CAINIAO_SUPER_ECONOMY&sku_id=12000044700000988&traffic_source=recommendation&type_rcmd=core

Вопросы
1--На какой предельной частоте дискретизации можно записывать семплы на ADC микроконтроллера STM32F407VE? 2 Msps при этом надо работать в режиме DMA.

2--Существуют ли ASIC микросхемы, которые делают квадратурный смеситель полностью аппаратно? Чтобы внутри был управляемый гетеродин NCO фазу (0.....360 градусов) и частоту (0 до 1MHz) которого можно менять по SPI в широком диапазоне. Или вовсе задавать несущую частоту извне подавая на пин. Чтобы на входе был ADC для подключения микрофона или фотодиода, а на выходе аналоговые значения I и Q. Желательно чтобы там еще внутри был Costas-loop для снятия с несущей BPSK модулированных сигнал.
Что-н типа AD9684,AD6674, SI4703 только подешевле и для акустических частот, а не для RF диапазона.

3--Если на выходе I/Q после фильтра нижних частот получился комплексный ноль, то как определить ошибку по фазе? Ведь нулевой вектор может быть направлен в любую сторону.

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

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

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

50%да1

50%нет1

Проголосовали 2 пользователя. Воздержавшихся нет.

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

0%да0

100%нет1

Проголосовал 1 пользователь. Воздержавшихся нет.