Адаптивный СВЧ-сенсор на базе 8-битного МК

от автора

Введение.
В последние годы наблюдается взрывной интерес к нейросетевым технологиям — эта тема уже набила оскомину. Однако в области встроенных систем и СВЧ-электроники применение «тяжёлых» нейронных сетей зачастую экономически и энергетически неоправданно.

Традиционно, нелинейность отклика СВЧ-детектора от частоты считается проблемой, требующей сложной программной коррекции. Но в данной работе этот «недуг» превращен в «подвиг»: разница в нелинейности двух разных микросхем стала основой для обучения нейросетевого частотного дискриминатора (рисунок 1).

Рисунок 1 – 3D-модель платы устройства

Рисунок 1 – 3D-модель платы устройства

Существуют актуальные концепции, вроде TinyML с библиотекой TensorFlow Lite, но и они остаются требовательными к вычислительным ресурсам. Особенно остро эта проблема стоит при создании распределённых систем контроля, где цена и потребление каждого узла имеют критическое значение. В данной статье предлагается альтернативный подход: построение адаптивного СВЧ-сенсора на базе двух амплитудных детекторов и отечественного 8-битного микроконтроллера К1946ВМ014 (аналог ATmega8535).

Вместо многослойных сетей используется простейшая линейная модель — однослойный персептрон, формально эквивалентный нейрону с функцией активации𝑓(𝑆), где 𝑆 — взвешенная сумма 𝑇 — порог.

𝑦=𝑓(𝑤1𝑈1+𝑤2𝑈2+𝐵)

Ступенчатая функция активации с несколькими порогами:

𝑦 = 0, если 𝑆<𝑇 1

𝑦 = 1, если 𝑇 1 ≤ 𝑆<𝑇 2

𝑦 = 2, если 𝑇 2 ≤ 𝑆<𝑇 3

𝑦 = 3, если 𝑆 ≥ 𝑇 3

Таким образом процесс сводится к задаче классификации данных получаемых АЦП МК. Такое решение позволяет:

·       реализовать калибровку и обучение «на лету» через простой терминал;

·       получить частотное разрешение за счёт добавления второго канала;

·       исключить необходимость юстировки каналов;

·       ограничиться вычислительными и энергетическими ресурсами 8-битного МК без потери адаптивности.

Статья описывает как аппаратную реализацию, так и алгоритм обучения, основанный на правиле Видроу-Хоффа(LMS-алгоритм), с акцентом на особенности целочисленной арифметики и ограничения относительно слабого микроконтроллера. Ниже представлена схема для проведения экспериментов (Рисунок 2).

Рисунок 2 – Схема экспериментального стенда

Рисунок 2 – Схема экспериментального стенда

Описание модели.

Для начала надо остановиться на описании модели используемого персептрона (рисунок 3).  Данная модель хорошо освещена в публикациях.

Рисунок 3 – Архитектура нейросетевого частотного дискриминатора

Рисунок 3 – Архитектура нейросетевого частотного дискриминатора

Слой входов (𝑋1,𝑋2) – это оцифрованные сигналы с наших детекторов, которые преобразуют энергию сигнала в постоянное напряжение.
Из технической документации к используемым в экспериментах устройствам (это детекторы серий AD8313 и AD8317) можно почерпнуть полную информацию об их характеристиках, в том числе частотный диапазон, динамический диапазон, а так же представление о переходной характеристике (рисунок 4 и 5).

Рисунок 4 – Типичная переходная характеристика детектора AD8317

Рисунок 4 – Типичная переходная характеристика детектора AD8317
Рисунок 5 – Типичная переходная характеристика детектора AD8313

Рисунок 5 – Типичная переходная характеристика детектора AD8313

Для AD8313 переходная характеристика дополнена иллюстрацией частотной зависимости. Использование в одном плече детектора с положительным наклоном характеристики (AD8313), а в другом с отрицательным наклоном (AD8317), позволило сформировать более выраженное пространство признаков, что упростило задачу классификации для единственного нейрона.

Весовые коэффициенты (𝑊1,𝑊2) – это «степень доверия» нейрона каждому детектору. Если AD8317 более линеен в нужном диапазоне, нейрон сам (в процессе обучения) назначит ему больший вес.

Блок сумматора (Σ): Необходим для сложения сигналов с учетом весов и добавляем Bias (смещение). Смещение нужно, чтобы «сдвинуть» шкалу в удобную нам область.

Квантователь (Пороги): В классических моделях здесь стоит функция активации (типа сигмоиды), но для нашей задачи на 8-битном МК идеально подходит описанная ранее ступенчатая функция. Она превращает аналоговую сумму в номер или класс диапазона.

Для реализации алгоритма обучения на 8-битном МК алгоритм Видроу-Хоффа был адаптирован к целочисленной арифметике. Поскольку стандартный коэффициент скорости обучения (𝐿𝑟) обычно составляет малую дробь (например, 0.00001), в данной работе он реализован через масштабный коэффициент (делитель). Операция W += (error * x) / 500000 эквивалентна классическому обновлению весов, но исключает использование ресурсозатратного float, что позволяет сохранить высокое быстродействие системы.

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

Описание работы программы.

Начнём с описания алгоритма. Микроконтроллер находится в бесконечном главном цикле (супер-цикле), ожидая команд, поступающих по интерфейсу UART. Для связи МК с ведущим устройством(ПК или управляющий МК) используется преобразователь USB–UART и программа-терминал («монитор порта») на персональном компьютере.

Для коммуникации с МК-персептроном предусмотрено шесть символьных команд:

·                 символы ‘0’, ‘1’, ‘2’, ‘3’– команды обучения. Мы сообщаем МК на какой частоте установили сигнал. В ответ получаем обновленные веса со смещением;

·                 символ ‘G’ –диагностика и получение сырых данные с АЦП;

·                 символ ‘T’ – команда тестирования (идентификация частотного диапазона). В ответ получаем решение персептрона о частоте сигнала, основываясь на актуальных весах и смещении.

В тексте программы, напротив важных для понимания строчек, даны комментарии – так проще и нагляднее, чем делать описание отдельно. Некоторые функции связанные с инициализацией периферии также включены в представленный ниже код. Однако необходимо напомнить, что настройки периферии уникальны именно для этой серии микроконтроллеров – К1946ВМ014. При желании перенести программу на другой чип – их придётся переписывать.

Текст программы полностью с комментариями:

#define F_CPU 8000000UL#include <avr/io.h>#include <util/delay.h>#include <stdio.h>#define TRAINING_ITER 100int16_t W1 = 0, W2 = 0; // Веса и смещениеint32_t B = 0;char MSG[60];const int32_t targets[] = {-10000, 10000, 25000, 45000}; // Класс 0 "притягиваем" к отрицательной области, остальные к положительнойconst char* range_names[] = {"Silence", "900MHz", "1200MHz", "1800MHz"};// Целевые уровни суммы для классов (Тишина, 900, 1200, 1800)void uart_init(uint32_t baud) {            // --- инициируем UART ---uint16_t ubrr = F_CPU / 16 / baud - 1;UBRRH = (uint8_t)(ubrr >> 8);UBRRL = (uint8_t)ubrr;UCSRB = (1 << RXEN) | (1 << TXEN);UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);}void uart_send(uint8_t data) {          // --- отправляем символ ---while (!(UCSRA & (1 << UDRE)));UDR = data;}char UARTReadChar(void) {            // --- читаем символ ---while (!(UCSRA & (1 << RXC)));return UDR;}void uart_print(const char *str) {  // --- отправляем строку ---while (*str) uart_send(*str++);}void ADC_init() { // --- АЦП ---ADMUX = (1 << REFS0); // Vref = AVCCADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);}uint16_t adc_read_avg(uint8_t channel) { // ---читаем и усредняем АЦП ---uint32_t sum = 0;ADMUX = (ADMUX & 0xF8) | (channel & 0x07);for(uint8_t i=0; i<32; i++) {ADCSRA |= (1 << ADSC);while (ADCSRA & (1 << ADSC));sum += ADC;}return (uint16_t)(sum >> 5);}void train(uint16_t x1, uint16_t x2, uint8_t target_idx) { // --- Математика Перцептрона ---int32_t sum = ((int32_t)W1 * x1) + ((int32_t)W2 * x2) + B;int32_t error = targets[target_idx] - sum;W1 += (int16_t)((error * (int32_t)x1) / 500000); // Коэффициенты Lr подобраны под 10-бит АЦПW2 += (int16_t)((error * (int32_t)x2) / 500000);B  += error / 2000;}uint8_t compute_perceptron(uint16_t x1, uint16_t x2) {int32_t sum = ((int32_t)W1 * x1) + ((int32_t)W2 * x2) + B;if (sum < 0)     return 0; // Класс 0: Silence       // Пороги разделения между targetsif (sum < 17000) return 1; // Класс 1: 900MHzif (sum < 35000) return 2; // Класс 2: 1200MHzreturn 3;                  // Класс 3: 1800MHz}int main(void) {ADC_init();uart_init(9600);while (1) {char cmd = UARTReadChar();if (cmd >= '0' && cmd <= '3') {           // Обучение: '0', '1', '2', '3' передаём классы.uart_send(cmd);uint8_t target_idx = cmd - '0';for (uint8_t i = 0; i < TRAINING_ITER; i++) {uint16_t a1 = adc_read_avg(0); // AD8313uint16_t a2 = adc_read_avg(1); // AD8317train(a1, a2, target_idx);_delay_ms(5);}snprintf(MSG, sizeof(MSG), " Class %s OK. W1:%d W2:%d B:%ld\n", range_names[target_idx], W1, W2, B);uart_print(MSG);}if (cmd == 'G') {  // Диагностика и сырые данные: команда 'G' - getuart_send(cmd);uint16_t a1 = adc_read_avg(0);uint16_t a2 = adc_read_avg(1);int16_t dif = (int16_t)a1 - (int16_t)a2;uint16_t div_int = 0, div_frac = 0;if (a2 > 0) {div_int = a1 / a2;div_frac = ((uint32_t)a1 * 100 / a2) % 100;}snprintf(MSG, sizeof(MSG), " A1:%u A2:%u df:%d dv:%u.%02u\n", a1, a2, dif, div_int, div_frac);uart_print(MSG);}if (cmd == 'T') {                           // Распознавание: команда 'T'uint16_t a1 = adc_read_avg(0);uint16_t a2 = adc_read_avg(1);uint8_t res = compute_perceptron(a1, a2);snprintf(MSG, sizeof(MSG), "Detected: %s\n", range_names[res]);uart_print(MSG);}}}

Прошивка и конфигурация микроконтроллера К1946ВМ014.

Для записи программы на плату с микроконтроллером использовался популярный и недорогой ISP-программатор. При разработке на плате была предусмотрена специальная колодка для записи программы на МК. Внешний вид платы с подключенным шлейфом ISP на фотографии (Рисунок 6). Так же видно колодку для подключения преобразователя USB–UART (RX TX VCC) и последующего сопряжения с ПК или внешним устройством.

После удачной компиляции и сборки мы наблюдаем отчёт о количестве занимаемой памяти:

                          Program Memory Usage      :      7854 bytes   95,9 % Full

                          Data Memory Usage         :      82 bytes   16,0 % Full

Всё поместились, но это из-за библиотеки<stdio.h> и функции snprintf(). Такой объем занимаемой памяти обусловлен наличием библиотек <stdio.h> и функции snprintf(), которые не являются необходимостью, но были оставлены для удобства чтения — оставим как есть.

Для прошивки МК воспользуемся популярной программой AVRDUDESS. Важным моментом является необходимость правильно установить Fusesbits.

Рисунок 6 – Плата МК с подключённым к ней программатором

Рисунок 6 – Плата МК с подключённым к ней программатором
Рисунок 7 – Пользовательский интерфейс программы загрузчика

Рисунок 7 – Пользовательский интерфейс программы загрузчика

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

Все опции для удачной записи программы видны в пользовательском интерфейсе (Рисунок 7). В диалоговом окне можно проконтролировать результаты сверки сигнатуры чипа, чтения/записи Fusesbits и записи программы.

Обработка первичных данных.

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

Есть аномалии в диапазоне 1600 МГц, т.к. делитель имеет неровную передаточную характеристику. Анализ первичных данных (таблица 1), полученных в ручную показал нелинейность,что создает трудности для порогового метода. Однако многофакторный (показания обоих детекторов сразу) анализ, выполняемый персептроном, позволяет разделить эти состояния (Рисунок 8). Траектория сигнала в пространстве признаков нелинейна, но кластеры целевых частот остаются линейно разделимыми.

Таблица 1.Отклики СВЧ-детекторов (900–2100 МГц)

Частота, МГц

A1 (AD8317)

A2 (AD8313)

Разность (df)

A1- A2

Отношение (dv)

A1/A2

Статус / Класс

Нет сигнала

132

336

-204

0.39

Класс 0 (Тишина)

900

264

181

83

1.45

Класс1

(GSM/LoRa)

1000

262

188

74

1.39

1100

285

150

135

1.90

1200

289

149

140

1.93

Класс 2

(Video FPV)

1300

293

155

138

1.89

1400

300

147

153

2.04

1500

278

183

95

1.51

1600

282

182

100

1.54

1800

335

133

202

2.51

Класс 3 (LTE/GSM)

1900

337

130

207

2.59

2100

298

167

131

1.78

Рисунок 8 – Финальный график сигнатур (df и dv)

Рисунок 8 – Финальный график сигнатур (df и dv)

Процесс обучения и результаты.

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

—        генератор сигнала, на базе синтезатора ADF4350;

—        управляющий микроконтроллер, для сопряжения с синтезатором по шине SPI и с МК-вычислителем по интерфейсу UART(а также для сопряжения с ПК для монитора порта).

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

Рисунок 9 –  Схема лабораторного стенда.

Рисунок 9 –  Схема лабораторного стенда.
Рисунок 10 –  Фотография лабораторного стенда

Рисунок 10 –  Фотография лабораторного стенда

Для оператора доступно семь символьных команд:

·                 символы ‘0’, ‘1’, ‘2’, ‘3’–это ручная установка частоты или выключение синтезатора. Так мы можем проверить работоспособность самого синтезатораADF4350.Или устанавливать частоту перед попыткой угадать, на уже обученном персептроне;

·                 символ ‘G’ –диагностика и получение сырых данные с АЦП;

·                 символ ‘T’ – команда тестирования (идентификация частотного диапазона). В ответ получаем решение персептрона о частоте сигнала, основываясь на актуальных весах и смещении;

·                 Символ ‘A’–автоматический режим обучения, который требует отдельного пояснения. Управляющий контроллер, получив команду от оператора ‘A’, выполняет следующую последовательность действий:

1) Устанавливает частоту. Это 900, 1200, 1800 МГц или выключает синтезатор.

2) Дожидается установки частоты с помощью сигнала от ADF4350 «lock detect»

3)Отправляет персептрону класс, соответствующий установленной частоте.

4) Повторяет цикл для всех четырёх состояний(тишина, 900, 1200, 1800 МГц). Для обучения классу «0» (Silence), управляющий контроллер использует пин на модуле синтезатора «CE» и программный Mute-режим, чтобы исключить паразитные наводки.

5) После завершения цикла получает от персептрона актуализированные веса и смещение.

Вся процедура для четырёх классов занимает примерно 12 секунд. Программа «монитор порта» позволяет отправлять символ или команду периодически. Выставляем интервал 20 секунд. Каждые 20 секунд проводим новое обучение и получаем актуальные веса и смещение. В любой момент времени можно остановиться и перейти в режим классификации с помощью команды ‘T ‘.

 Запускаем автоматическое обучение, и смело уходим на обед. За это время персептрон пройдет в районе 300 эпох. Как долгожданный результат — сходимость весов. Ура! Характерным признаком сходимости весов является низкая флуктуация значений весов и смещения. Колеблются вокруг установившихся целочисленных значений W1:160, W2:-140, B:-80.Теперь можно подать тестовые сигналы и убедиться, в работоспособности обученной нейросети. Ниже (Рисунок 11) предоставлен лог из монитора портас результатами последней эпохи обучения и последующим тестированием.

Рисунок 11 – Данные из монитора порта(вывод весов после обучения и результат классификации по команде T.

Рисунок 11 – Данные из монитора порта(вывод весов после обучения и результат классификации по команде T.

Заключение.

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

Успешная сходимость весов на 8-битном микроконтроллере открывает интересные перспективы для развития концепции адаптивных сенсоров. Поле перцепции данной системы легко расширяется, например:

— Добавление датчика температуры позволит нейрону автоматически компенсировать температурный дрейф детекторов.

— Внедрение третьего канала на другой частотный диапазон или учёт суммарной мощности сигнала позволит создать систему, полностью инвариантную к амплитуде входного воздействия.

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

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