Приветствую всех любителей электроники!
Данная статья ориентирована на людей со средним («молодым»?) уровнем знаний в электронике и выше.
Используемые сокращения в статье
АЧХ — Амплитудно-частотная характеристика
МК — Микроконтроллер
БПФ — Быстрое преобразование Фурье
ДПФ — Дискретное преобразование Фурье
Бывают ситуации, когда нам известен спектр сигнала, но форму сигнала мы не можем представить в виду сложности основого сигнала. Ещё чаще возникает вопрос об построении АЧХ, но вот прибора под рукой нет, особенно если работаешь в гаражном кооперативе дома.
В данной статье я хочу поделиться скромным девайсом, моделирующее аналоговый сигнал сложной формы математическим методом и способное построить АЧХ по данному сигналу.
«Математическим методом!?»
Да, на устройство ничего не будет подаваться из-вне. Всё моделирует, строит и вычисляет непосредственно микроконтроллер. Я специально выделил это место, чтобы не обнадёживать людей, которые хотят увидеть полностью законченный и работающий измерительный прибор.
/*кхе-кхе*/
Да, цифры перед фамилией для университета, я студент, параллельно работающий техником (программирование STM32)
Краткие сведения
Для разработки устройства нам потребуется:
-
Любая отладочная плата с МК семейства STM32F1xx. В моём случае это

Характеристики SPI1 Подробнее об этом этапе
Тут можно выбрать любой МК семейства F1 как было сказано ранее, у них всё одно и тоже, в том числе и распиновка SPI и АЦП. Способ программирования у меня стоит по SWD. Выбирайте как вам удобно, с этим понятно.
Также включаем АЦП. Задействуем 3 канала АЦП, под одну составляющую гармонического сигнала отводим 1 канал АЦП. Забирать данные с АЦП будем при помощи DMA в режиме прерывания. АЦП и DMA выставим в одиночном режиме, будем вручную выключать АЦП и включать, когда это будет нужно. Не забудьте включить прерывание по DMA!
Характеристики АЦП Кроме этого, активируем ещё 3 вывода МК, настроем их как выходы и присвоим названия. Данные выводы будут использованы для управления дисплеем. Выбор драйвера (chip select), сброс (reset), и разрешения записи данных (data chip).
Помимо этого нужно конечно же подать питание, и включить подсветку. Подсветку можно сделать постоянную, а можно организовать регулируемую, через транзистор с помощью таймера в режиме ШИМ. Питание и подсветку я подавал от самой платы…

Теперь перейдём в дерево тактирования (clock tree) и разгоним МК до максимально допустимой частоты в 72МГц.
Тактирование микронтроллера Стоит заметить, что в таком положении частоту АЦП можно выставить только на 12МГц, при 14МГц возможных. Чтобы выставить максимум, необходимо понизить частоту системной шины. Однако в данном проекте АЦП не выполняет сверхважную задачу, поэтому оставляем 12МГц.
Разработка программы для микроконтроллера
Прежде всего необходима библиотека для дисплея на базе ILI9341. В интернете есть множество вариантов готовых библиотек для данного дисплея, однако в большинстве своём они ограничены, тяжелы в понимании за счёт отсутствия эстетики написания кода, могут вообще не работать или написаны под какое-то конкретное семейство STM32. Поэтому было принято решение написать универсальную для любого семейства STM32 библиотеку уже с полным набором удобных функций на базе библиотек из интернета, однако данная библиотека подходит для любого драйвера, так как она написана на CMSIS. Таким образом её можно подключать в любой проект. Саму инициализацию SPI будет делать CubeMX (так быстрее, при желании скину код инициализации SPI на CMSIS с возможностью разгона частоты до 44МГц). Инициализацию библиотека делает сама. Она имеет понятные названия функций, их легко использовать.
Основные функции:
1)
void taskSolution (uint16_t k);Данная функция решает основное уравнение, описывающее гармонический сигнал, подготавливая значение выборки для удобного вывода на дисплей. Для данного проекта выбрано следующее уравнение:где in – это частота гармоники, величина которой зависит от изменения на входе канала АЦП;
k – номер выборки;
N – количество выборок (N = 256);
void taskSolution(uint16_t k){ firstHarm = 1.0 * cos(((2*PI)/X_LINE_LENGTH)*firstHarmFreq*k + PI/2); //значение 1-ой гармоники secHarm = 1.0 * cos(((2*PI)/X_LINE_LENGTH)*secHarmFreq*k + PI/2); // 2-ой thirdHarm = 1.0 * cos(((2*PI)/X_LINE_LENGTH)*thirdHarmFreq*k - PI); // 3-ей Fk = firstHarm + secHarm + thirdHarm; // Сложеник гармоник и получие выборки //Главное уравнение: //Fk = (1.0 * cos((2*PI/N)*0*k + PI/2) + 1.0 * cos((2*PI/N)*2*k + PI/2) + 1.0 * cos((2*PI/N)*3*k - PI)); Fk = ((Fk*MULT_SIGNAL_VAL)+START_POINT_Y); // конверсия значения для отображения на экран }Само собой функция стоит в цикле до некого опеределённого значения, в данном случае 256 выборок (
X_LINE_LENGTH). По мимо этого в конце функции я зачем-то делаю конверсию. Тут всё просто. Я использую функцию косинуса и значит у меня значение колеблется от 0 до 1, это понятно. Значит мне его нужно просто умножить на некую константу, чтобы удобно было вывести уже большое значение (номер пикселя) на экран + это помогает сразу получить из «плавующей» переменной довольно точную целую.2)
uint32_t MAP (uint32_t au32_IN, uint32_t au32_INmin, uint32_t au32_INmax, uint32_t au32_OUTmin, uint32_t au32_OUTmax);Данная функция конвертирует диапазон изменения значения АЦП (0-4095) в диапазон частот сигнала (0-15);3)
void displaySignal (uint16_t k);Данная функция выводит полученное значение выборки на дисплей;4)
void clearNextPosition (uint16_t k, uint16_t COLOR).Перед выводом на дисплей используем функцию очистки следующего значения выборки. Так как экран обновляется в данном случае слева направо, и чтобы не очищать сразу весь участок сигнала (устранение мерцания), а добиться плавности отображения изображения очищаем только следующий столбец пикселей экрана;5)
void visualSignalIncrement (uint16_t k, uint16_t COLOR);Чтобы визуально сигнал был хорошо различим, зажжём сверху и снизу основного значения функции ещё один пиксель, таким образом сигнал будет жирнее;6) Функции:
void visualFFT_Increment (uint16_t k, uint16_t harmonic, uint16_t COLOR);void displayFFT (uint16_t k); void clearLastFFT_VAL (uint16_t k);void displayFFT_VAL (uint16_t k);аналогичны функциям вывода сигнала на экран. Принцип работы такой же, отличие заключается только в определении амплитуды и частоты каждой гармоники, и расчёт спектра сигнала;
Нюанс построения АЧХ в проекте
Я не использовал сложные формулы для вычисления спекртра в данном проекте. Т.к. мне известна формула гармонического сигнала, его параметры, я просто брал значение его аплитуды и частоты и рисовал соответсвующую гармонику на АЧХ. В дальнейшем конечно, устройство можно доработать, тем более, что это может лишь показаться сложным на первый взгляд. Если хочется понять принцип работы алгоритма БПФ и ДПФ, на harb есть понятная и позновательная статья на данную тему, там использован другой язык и нет микроконтроллера, но это не важно, поскольку очень понятно описывается сам алгоритм, чтобы вы могли применить его у себя в проекте.
7) Для отслеживания параметров сигнала и спектральных характеристик необходимо нарисовать координатные оси с соответствующими значениями. Данную операцию выполняют функции
drawGridSignal(BLACK); drawGridFFT(BLACK);Из названия функции можно увидеть, что первая функция отвечает за отрисовку координатной оси для гармонического сигнала, а вторая для АЧХ. Количество выборок: 256 (X_LINE_LENGTH). Максимальная частота гармоники: 15 Гц (LIMIT_FREQ);
Процесс сборки устройства
Устройство мне необходимо было сделать довольно быстро для своих нужд, но так, чтобы ничего не развалилось и нормально работало. Поэтому плату я не делал, это было бы долго и дорого, даже если не учитывать около недели на разработку платы, китайцы бы везли платы больше месяца + они стоили бы около 25-35$. А так плат с STM у меня в избытке, как и программаторов с иными коплектующими, поэтому, условно, собрал из того, что было, не задумываясь над ценой конструкции. Разве что покупал пластиковый корпус, так как у меня пока нет своего 3D-принтера, увы… Вырезать пластиковый корпус конечно то ещё удовольствие и не очень красиво выходит по итогу, но тут уж как говорится:
«Лучше сделать и пожалеть, чем не сделать и потом жалеть» ?
Внутреннее строение устройства Все исходники я выложил на GitHub. Там вы можете скачать проект в CubeMX и сам проект в Keil uVision5. Проект должен завестись сразу же, файл библиотеки уже подключён в проект, ничего стороннего скачивать не нужно.
По вопросам моего самодельного программатора и прочим пишите в комментариях. Кроме этого недавно приехали https://habr.com/ru/articles/741232/


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