Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр
Игра рыбалка представляет собой полноценный симулятор рыбалки и дает возможность порыбачить в реально существующих местах из жизни и поймать рыбу, которая там обитает.

Рыбный дождь

Спорт, Симуляторы, Рыбалка

Играть

Топ прошлой недели

  • AlexKud AlexKud 38 постов
  • SergeyKorsun SergeyKorsun 12 постов
  • SupportHuaport SupportHuaport 5 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня

Stm32

С этим тегом используют

Микроконтроллеры Электроника Arduino Программирование Своими руками Все
106 постов сначала свежее
DELETED
5 лет назад
Лига Радиолюбителей

CAN-сниффер на STM32F0x2⁠⁠

CAN-сниффер на STM32F0x2 Stm32, USB, Длиннопост

(заранее извиняюсь за отсутствие кусков кода в тексте: редактор пикабу не позволяет воткнуть достаточно длинные посты, да и нет никаких тегов для оформления исходников, оригинал можно прочитать у меня в ЖЖ; и вообще, на пикабу крайне неудобный редактор постов, в ЖЖ все намного удобней).

Саму основу для сниффера я сделал еще давно — когда необходимо было разработать девборду для "тренировок" с USB и CAN (под контроллеры термодатчиков):

Протокол работы железки я уже описал, теперь опишу исходники ее прошивки.


Итак, первое, что нам нужно для работающего CAN-сниффера — это возможность одновременной работы и CAN, и USB. В дешевой нише STM32 это умеют STM32F0x2 (072 и 042; на работе для термодатчиков я закупал 042, для дома же купил на али 2 десятка 072, тогда это было примерно 60 рублей за штучку).

В отличие от 103-х, где служебный буфер в памяти CAN и USB делять не "по-братски", и он может принадлежать лишь одной из периферий, в 0x2 CAN забирает лишь 256 последних байт буфера USB. Поэтому для USB доступно 768 байт буфера (в принципе, этого вполне достаточно, если не делать сложное составное устройство).

Начнем с USB. Сниффер будет "выдавать" себя за PL2303 (мне нравится, что модуль ядра выделяет для него устройство /dev/ttyUSBx, а не позорный /dev/ttyACMx, как под обычный USB-CDC; кроме того, в некоторых некошерных дистрибутивах вроде бубунты могут быть проблемы с USB-CDC: при подключении запускается modemd и захватывает файл устройства в свое личное распоряжение).

В заголовочном файле usb_defs.h определяем USB_BTABLE_SIZE как 768 байт. Там же определяем размеры буферов конечных точек 0 и 1 (конечная точка 1 — interrupt IN — использоваться при работе не будет, и в принципе можно было бы ее не определять). Там же нам понадобится определить структуры служебных регистров и регистров описания конечных точек.

В файлах usb_lib.c и usb_lib.h разместим "низкоуровневые" функции USB. В принципе, эту иерархию не я придумал: когда я только начал заниматься USB, вменяемой реализации на просторах интернета не нашел. Один из пользователей easyelectronix выложил простую реализацию USB-HID. Собственно, на основе ее я и сделал свои экземпляры USB-HID, CDC и эмуляцию PL2303.

В заголовочном файле определим различные стандартные типы запросов и прочее, что нам понадобится (строки с 35 по 77). Простые макросы для понимания, является ли пакет входящим или исходящим и есть ли там данные SETUP. Для работы с регистрами конечных точек нам понадобится определить пару макросов: KEEP_DTOG_STAT и KEEP_DTOG.


Здесь сразу скажу: надо помнить, что в регистрах EPnR некоторые флаги имеют свойство toggle. Поэтому не повторяйте моих ошибок: держите это всегда в уме, и когда нужно лишь какой-то флаг установить/сбросить, обнуляйте биты всех ненужных toggle-флагов! Эти макросы собственно и занимаются тем, что оставляют нетронутыми флаги DTOG (они нам не нужны, т.к. мы не пользуемся двойной буферизацией) и STAT (а это важно, когда мы получаем данные, но не хотим сразу же отправлять ACK, пока буфер не будет обработан).Еще для работы конечного автомата состояния USB понадобится определить его состояния. Там же определяем макросы для задания строковой информации (_USB_STRING_, _USB_LANG_ID_) и вспомогательные структуры для разбора конфигурационного пакета (config_pack_t), настройки конечной точки (ep_t) самого USB(usb_dev_t — эта структура используется, чтобы поменьше глобальных переменных заводить). Из /usr/include/linux/usb/cdc.h копируем определение структуры usb_LineCoding (в принципе, можно обрабатывать SET_LINE_CODING, меняя скорость, скажем, USART1; но в данном случае это не нужно, а USART1 у меня использовался исключительно для отладочных сообщений).

В файле usb_lib.c определяем дескрипторы устройства (достать их несложно, если "натравить" на "настоящий китайский" PL2303 утилиту lsusb -v). Здесь же как WEAK определены заглушки для обработчиков стандартных запросов SET_LINE_CODING (изменение параметров последовательного порта: скорости, четности и т.п.), SET_CONTROL_LINE_STATE (аппаратное управление потоком) и SEND_BREAK (конец связи).

В отличие от "обычного" USB CDC у pl2303 есть еще и vendor-запросы. Нафиг они нужны — непонятно, однако, благодаря тому, что кто-то уже отреверсил подобную железяку и написал для нее модуль ядра, в исходниках /usr/src/linux/drivers/usb/serial/pl2303.c можно посмотреть, как оно работает. Собственно, оттуда я и утащил функцию-обработчик vendor_handler(config_pack_t *packet).

Возможно, в оригинале эти запросы таили что-то эдакое, но в ядре они используются лишь для идентификации — что на том конце действительно PL2303. Во всяком случае, с таким минимумом устройство работает и под android (возможно, будет работать и под игровыми приставками, мне это безразлично).

При работе со строковыми дескрипторами иногда может оказаться, что дескриптор не влезает в стандартный объем 64-байтной посылки (особенно большими размерами славятся HID-дескрипторы), поэтому такие вещи надо разбить на несколько посылок. Отправляются такие дескрипторы только в начале коннекта, поэтому я решил не заморачиваться с конечным автоматом, а сделать блокирующую запись: static void wr0(const uint8_t *buf, uint16_t size). Здесь еще надо было учесть, что если мы отправляем в последней посылке ровно 64 байта, то нужно еще и ZPL — посылку нулевой длины — отправить.

Работать с USB мы будем на прерываниях, поэтому все самое интересное начинается в обработчике прерывания usb_isr().

Здесь мы обрабатываем такие прерывания, как RESET — хост говорит устройству, что нужно заново инициализировать USB, CTR (correct transfer) — прерывание по приему или передаче данных, а также вспомогательные SUSP и WKUP — "засни" и "проснись".


В обработке OUT-запросов (т.е. входящих для устройства) пришлось пойти на хитрость: т.к. некоторые вещи (как тот же LINECODING) передаются в "два захода", необходимо отдельно заполнять данными setup_packet и вспомогательный ep0databuf (где и лежат эти данные по установке LINECODING). Данные для LINECODING приходят так: сначала без флага SETUP приходит нужная информация, а потом уже с этим флагом — команда запроса SET_LINECODING. И, соответственно, вызывается процедура обработчика запроса.

Чтобы USB корректно работало, сначала нам надо настроить все конечные точки: выдать им адреса и размеры буферов, определить направление, задать функцию-обработчик. Это делается в EP_Init.

Кому-то нравится руками задавать адреса буферов данных, я же решил все упростить — в переменной lastaddr хранится последний свободный адрес в буфере (при RESET эта переменная реинициируется на начало буфера). Дальше все по коду понятно.

Для разбора данных, поступающих на управляющую точку EP0, вызывается функция EP0_Handler. Из остальных конечных точек, как я уже говорил, точка EP1 у нас хоть и определена, но не используется. А для приема/передачи заводим односторонние точки EP2 и EP3 (все эти данные хранятся в дескрипторе устройства, поэтому размеры буферов и направление передачи конечных точек нужно согласовывать с данными в дескрипторе). Их обработчики будут уже в другом файле — с более высокоуровневыми вещами.

У STM32F0x2 регистры данных USB_TX пишутся по 16 бит (в STM32F103 эмулируется 32-битное хранилище, т.е. писать надо как 32-битный блок, но активны там только 16 бит), а USB_RX вообще можно читать побайтно (у 103 они тоже эмулируют 32-битные блоки). В общем, здесь все проще. EP_WriteIRQ отличается от EP_Write тем, что вызывается внутри обработчиков прерывания, поэтому в ней флаги EPnR не меняются.

В файле usb.c лежат сравнительно высокоуровневые функции (правда, я и USB_setup зачем-то здесь оставил).

Собственно, настройка USB и начинается с USB_setup. Тактируем USB от HSI48, что позволяет не цеплять внешний кварц. Используем автокоррекцию HSI48 от USB SOF. Для начала разрешаем только прерывания RESET и WKUP (остальное будем разрешать уже после настройки конечных точек).

IN/OUT запросы данных обрабатываем фукнциями transmit_Handler() и receive_Handler(). Обработчик IN (выходящие данные) ощичает флаг CTR_TX и выставляет внутренний флаг tx_succesfull (говорящий о том, что предыдущая посылка отправлена и можно отправлять следующую). А в обработчике OUT (входящие данные) мы выствляем внутренний флаг rxNE (говорящий, что в буфере есть данные и их можно считать) и очищаем флаг CTR_RX. Выставлять ACK мы будем лишь после того, как данные из буфера будут обработаны!

Для того, чтобы не блокировать МК на время отправки мелких объемов данных (а в основном они значительно меньше 64 байт), в функции USB_send есть возможность "отложенной" отправки данных (последняя строчка просто помещает маленькие объемы данных во вспомогательный буфер, который будет отправлен в последующем при помощи функции send_next()).

Из основного цикла main на каждом проходе надо запускать функцию usb_proc. Здесь анализируются состояния КА USB. Скажем, в состоянии USB_STATE_CONFIGURED (EP0 настроена, все дескрипторы отправлены) нужно настроить остальные конечные точки. В состояниях USB_STATE_DEFAULT (начальное) и USB_STATE_ADDRESSED (только прошла процедура адресации) USB еще пользоваться нельзя — поэтому снимаем флаг usbON. А в состоянии USB_STATE_CONNECTED вызываем ту самую send_next().

Более высокоуровневую функцию USB_receive вызываем уже откуда-нибудь извне. Она возвращает количество считанных данных и заполняет ими буфер. Ну, а т.к. данные теперь надежно сохранены, можно отправлять хосту ACK.


Уже в main.c размещаем функцию буферизованного чтения из USB с выставлением флага готовности по '\n'. Здесь происходит эхо введенных символов и обработка backspace (чтобы можно было удалять неправильно набранные символы).


ОК, с USB закончили. Пора переходить к CAN.


В can.h определим структуру CAN_message. В ней содержатся данные (до 8 байт) для стандартной CAN-посылки, длина данных и идентификатор получателя этих данных. И определим флаги состояния CAN.

В can.c определяем основные функции для работы с CAN. Входящие данные буферизуются в массиве messages[CAN_INMESSAGE_SIZE].

Настройку CAN делаем по сниппетам. Разве что аргументом этой функции является скорость в кбод, поэтому проверяем в начале, допустимым ли является значение скорости.

Поначалу фильтр позволяет принимать абсолютно все сообщения: нечетные в FIFO0 и четные в FIFO1. Далее фильтры можно будет перенастроить.

В отличие от USB, у CAN в прерывании анализируются лишь ошибки, а вот для работы с данными из main постоянно запускается can_proc(). Здесь рассматриваются различные флаги и обрабатываются ошибки линии: если на шине нет никого, либо накапливается много ошибок, CAN переинициализируется.

Функция can_send(uint8_t *msg, uint8_t len, uint16_t target_id) отправляет сообщение msg длиной len с идентификатором target_id. В принципе, можно было бы уменьшить количество аргументов этой функции, если поместить эти данные в обертку — структуру CAN_message. Функция находит первый свободный "почтовый ящик", заполняет в нем регистры данных и инициализирует посылку.

Функция can_process_fifo(uint8_t fifo_num) запускается при наличии данных в соответствующем буфере FIFO. Все данные помещаются в массив-буфер, откуда впоследствии их можно считать. Если буфер полон, то функция "надеется", что к следующем запуску можно будет его опустошить (иначе происходит переполнение FIFO — ничего с этим не поделать).


Как все это работает.


При получении определенной команды по USB, она анализируется (proto.c), и если это команда на передачу данных (s), запускается функция sendCANcommand. В ней происходит парсинг введенных пользователем данных, и если все ОК, то отправляется сообщение.

При поступлении сообщения с CAN, его содержимое выводится на терминал.

Для упрощения создания фильтров я добавил еще и софтовый фильтр — для возможности отклонения сообщений с ID из списка (иначе пришлось бы лепить аппаратный фильтр с нужной маской и ID, а считать-то лень!).

Функция add_filter позволяет добавить или удалить (если фильтр не содержит данных) фильтр с номером от 0 до 27. Т.е. можно удалить фильтры по умолчанию и заменить их своими. В функции идет довольно-таки длинный парсинг текстовых данных: разбирается, в каком режиме фильтр (список или маска), а далее заполняются сами данные фильтра.

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

CAN-сниффер на STM32F0x2 Stm32, USB, Длиннопост
Показать полностью 2
[моё] Stm32 USB Длиннопост
29
25
ahhx3m
5 лет назад
Arduino & Pi

STM32F429I Discovery + SDRAM + LTDC под Arduino IDE⁠⁠

Сижу на карантине и придумываю себе сложности. Дома валяется STM32F429I Discovery, вот и решил проверить возможности Arduino IDE для программирования STM32 и данной платки в частности.


Для начала нужно поставить STM32 Cores под Arduino IDE. Детально этот процесс расписан тут https://github.com/stm32duino/wiki/wiki/Getting-Started так что не буду повторяться, тут ничего сложного.


Мне немного не повезло, так как именно этой платки нет в этой сборке, но это не проблема. Можно добавить практически любую стандартную отладочную STM32 вручную, так как драйвера есть в комплекте под большое количество чипов. Вот тут лежит инструкция по добавлению новой платы https://github.com/stm32duino/wiki/wiki/Add-a-new-variant-(board) Но я напишу вкратце со своими конфигами:


1) добавить плату в файл boards.txt (у меня он находится тут ...\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.8.0\boards.txt) - тут нужные строки  - https://github.com/levkovigor/stm32f429i-disk1_sdram_ltdc/bl...

2) добавить настройки пинов для платы - в папку ...\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.8.0\variants добавить папку https://github.com/levkovigor/stm32f429i-disk1_sdram_ltdc/tr...


Теперь в меню выбора плат в Arduino IDE в разделе Discovery появится наша платка.


После добавления платы я проверил все стандартные возможности:

цифровые входы/выходы, аналог, шим, уарт, SPI, I2C, прерывания, freertos и т.д.

В большинстве случаев все отлично работает, но некоторые вещи с дополнительными костылями под stm32


Также отлично завелся гироскоп, который есть на плате через библиотеку Adafruit_L3GD20 (только старую, в которой есть SPI, а не I2C)


После этого всего я дошел до экрана и тут началось веселье. Контроллер экрана здесь стоит ILI9341, поэтому для начала я попробовал завести его через SPI и библиотеку Adafruit_ILI9341. С небольшими допилами это получилось - нужно было добавить вручную инициализацию пинов под SPI:


__GPIOC_CLK_ENABLE();

__GPIOD_CLK_ENABLE();

__GPIOF_CLK_ENABLE();

GPIO_InitTypeDef GPIO_InitStruct;

GPIO_InitStruct.Pin = GPIO_PIN_2;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_LOW;

HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_13;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_LOW;

HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;

GPIO_InitStruct.Alternate = GPIO_AF5_SPI5;

HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);


Но скорость отрисовки через SPI не порадовала, а с учетом того, что особенностью данной платы есть возможность работы экрана через SDRAM , то начал ковырять все это дело. С драйверами под это все в stm32 cores проблемы, поэтому пришлось делать на регистрах.


Сначала прикрутил SDRAM  https://github.com/levkovigor/stm32f429i-disk1_sdram_ltdc/bl...

командами SDRAM_Read8 и SDRAM_Write8 можно записывать/считывать значение в памяти по адресу.


После этого прикрутил LTDC - для работы экрана через память - https://github.com/levkovigor/stm32f429i-disk1_sdram_ltdc/bl...

команда PutPixel меняет цвет пикселя по координатам x, y


Осталось только перевести экран в соответствующий режим работы, для этого нужно задать набор команда по SPI конроллеру ILI9341 - для этого я использовал все ту же библиотеку Adafruit_ILI9341, в которую дописал функцию begin_ltdc() - доработанные файлы библиотеки также лежат в репозитории.


Ну и видео на котором можно оценить разницу в скорости работы двумя методами: заливка экрана черным > синим > красным с задержкой в одну секунду через SPI и LTDC.

Кстати тачскрин тоже работает, для этого нужна библиотека Adafruit_STMPE610, тут только пини для I2C надо правильные задать.


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

Показать полностью 1
[моё] Stm32 Arduino Tft Видео Длиннопост
22
3
boris112
5 лет назад

Схема подключения жала HAKKO T12 к плате KSGER на STM32⁠⁠

Всем привет, заказал плату контроллера для жал Т12 от KSGER на STM32, отдельно заказал жала, термистор и ртутный выключатель. Хочу собрать всё в кучу с самодельной ручкой из стальной трубки, диаметром 10 мм.

Так вот, характеристиках на плату у продавца есть схема подключения на которой к корпусу картриджа идёт одновременно два провода "N" и "E". Спросил у продавца, он ответил, что схема правильная.

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

Я запутался, помогите разобраться

Схема подключения жала HAKKO T12 к плате KSGER на STM32 Stm32, Ksger, Hakko T12, Паяльник, Подключение
Схема подключения жала HAKKO T12 к плате KSGER на STM32 Stm32, Ksger, Hakko T12, Паяльник, Подключение
Показать полностью 2
Stm32 Ksger Hakko T12 Паяльник Подключение
3
DELETED
5 лет назад

Как я поздравил друзей с 2020⁠⁠

Как Вы поздравили своих друзей в 2020 году?

[моё] Stm32 2020 Видео
14
9
PetroBr
5 лет назад

Дисплеи смартфонов, дешевле 4 раза чем радиолюбительские к ардуино⁠⁠

Появилось время, разобраться в подключении дисплеев к микроконтроллерам ( в моем случае stm32), и с удивлением обнаружил что самые дешевые (цветные) , в магазинах начинаются от тысячи. И как то не стыковочка получается в ценах. Почему за полторы тысячи рублей можно уже купить целый смартфон, и дисплеи к ним стоят от 250р. А к всяким ардуинкам они стоят не меньше 1200р. (Меньше не нашел). В чем подвох между этими дисплеями и разница? Есть ли примеры использования дисплеев смартфона для изображений от МК?

[моё] Stm32 Жк-дисплей Текст
11
37
techn0man1ac
techn0man1ac
5 лет назад
Лига Радиолюбителей

Разработка схемы и печатной платы (STM32)⁠⁠

Авторские описания роликов:

"Детально показан процесс создания макетной платы с микропроцессором STM32F0. Как самостоятельно проектировать схемы с использованием микроконтроллеров. Основы проектирования печатных плат."

Автор показал вес процесс создания электроники, от идеи до работающего устройства. Как оказывается это не так сложно, как могло бы показаться.

За видео благодарим автора youtube канала "Vladimir Medintsev"

Показать полностью 2
Схема Плата Электроника Stm32 Разработка Устройство Видео
16
156
techn0man1ac
techn0man1ac
5 лет назад
Arduino & Pi

STM32F103C8T6 самодельный USB микрофон⁠⁠

Авторское описание:
stm32f103c8t6 самодельный USB микрофон построенный на базе микрофонного модуля MAX9814. Весь звук для видео был записан на этот микрофон. Применен самый популярный микроконтроллер stm32f103c8t6, любители ардуино его называют STM32 Blue Pill.

Работа микрофона была проверена на windows7 32\64 битной версии и на linux (операционная система Raspbian rasperry pi 3b).АЦП работает на скорости 256kHz, затем частота дискретизации понижается до 32kHz путем усреднения каждых 8 выборок АЦП. Дабы избавить ВАС от проблем со сборкой проекта я предоставляю готовый hex файл для прошивки.

Который можно легко залить не имея программатора под руками, это подойдет любителям ардуино. Инструкции по прошивке есть в видео.

За видео благодарим автора канала "ElectroHobby"

Показать полностью
Stm32 Микрофон Своими руками Электроника Видео
34
10
Mrtrol2018
5 лет назад

AudioSwitcher — автоматизация того, что казалось бы не нужно автоматизировать⁠⁠

AudioSwitcher — автоматизация того, что казалось бы не нужно автоматизировать Stm32, Аудиофилия, Схемотехника, Печатная плата, Микроконтроллеры, Радиолюбители, Электроника, Длиннопост

Предисловие

У меня дома есть пара комплектов хороших советских акустических систем. Но техника эта довольно старая и просто не может включаться с пульта или автоматически, а постоянно подходить к усилителю звука и включать/выключать его просто лень. Это проблему я и решил. Сначала была куплена ардуино и проект был сделан на ней, но качество работы меня не устроило и проект был переделан под STM32F103C8. В итоге у меня получилось устройство, которое имеет 4 аудио-входа, 1 аудио-выход, вход 220В и выход 220В. При наличии хотя бы одного активного аудио-входа на выходе 220В появляется напряжение, тем самым включая усилитель звука, и активный аудио-канал передается на выход.

Сложности при разработке

Казалось бы все просто: если АЦП получает не 0, тогда считать канал активным. Все почти так, но это работает только если включить источник аудио-сигнала и выключить на нем звук. При выключенном состоянии разные устройства дают разные помехи, тк они не полностью обесточены. Да и у плохих источников звука микроконтроллер мог улавливать помехи при выключенном звуке, причем довольно сильные. И это именно помехи источника, помехи на моей внешней аудиокарте STMка не видит, более того тихий звук с нее — 0.

Как сделать себе такое?

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

Что нам понадобится:

печатная плата
программатор ST-Link v2
1 чип STM32f103C8
4 реле для коммутации входного аудио-канала на выход
1 реле для коммутации 220В для включения усилителя
AC-DC понижающий преобразователь 220В — 5В(можно взять со старой зарядки телефона)
сетевой провод и разъем для подачи тока нашему устройству и усилителю
розетка
резисторы, конденсаторы и другая мелочь

Естественно нам понадобятся аудио-провода и minijack штекера с гнездами.

Хотелось бы заострить внимание на выборе реле… Если с выбором 220В реле все предельно понятно: оно должно «уметь» коммутировать 220В переменное напряжение и управляться 3.3В. То с выбором звуковых реле не все так просто. Далеко не каждое реле, даже твердотельное, не будет давать помехи на выходе, а нам это очень важно. Я живу в Минске и не смог ничего найти подходящего и по адекватной цене, поэтому были заказаны с известного китайского магазина 4 реле PVT322A. Возможно в вашем регионе вы сможете найти что-то подешевле.
Схема и разводка печатной платы :

AudioSwitcher — автоматизация того, что казалось бы не нужно автоматизировать Stm32, Аудиофилия, Схемотехника, Печатная плата, Микроконтроллеры, Радиолюбители, Электроника, Длиннопост
AudioSwitcher — автоматизация того, что казалось бы не нужно автоматизировать Stm32, Аудиофилия, Схемотехника, Печатная плата, Микроконтроллеры, Радиолюбители, Электроника, Длиннопост

Раз уж начали, то продолжим изучать аппаратные особенности. На схеме, которую вы можете найти в репозитории в папке Eagle нужно подобрать токоограничительные резисторы(R4-7) под ваши реле. В моем случае это 30 Ом. Так же есть катушка L1: выбирайте любой фильтр, сглаживающий высокочастотные помехи.

Заказать печатную плату вы можете на PCBWAY или JLCPCB. Цены у них низкие, я заказывал у JLCPCB и они выставили мне счет всего в 2$. При заказе печатной платы вам нужны будут гербер файлы, вы из сможете найти все в той же папке или сами сгенерировать.

Перейдем к программной части


Рассказывать как подключить программатор к компьютеру, установить среду программирования и драйвер я не буду, т.к. этих инструкций очень много и они предельно доступные. На моей схеме предусмотрены выходы для программаторы. Я использовал Visual Studio 2017 + VisualGDB. Скачав проект из того же репозитория мы сможем открыть проект. Сразу же обратим на файл Settings.cpp.

#define DEBUG0 0//init USART and send all measurement values
#define DEBUG1 1//init USART and send information about recognition music or not
#define DEBUG2 0//just init USART
#define MaxEqualToZeroValue 3 //the value which equal or less is equated to zero
#define MaxAvarageForNoise (float)0.4//this is max avarage of measurement values so that the sound is considered noise for NOT active channel
#define MaxAvarageForActiveNoise (float)0.06//this is max avarage of measurement values so that the sound is considered noise for active channel
#define CountOfConsecutiveZeroValueForNoise 250//if count of consecutive zero values bugger it that sound is equated to noise
#define MinCountOfZeroValue 550//it's minimum count of zero values to equate to music(not consecutive)
#define USE_LED 1
#define LED_GPIO_PERIPH RCC_APB2Periph_GPIOC
#define LED_GPIO_GROUP GPIOC
#define LED_GPIO_PIN GPIO_Pin_13
#define USE_AMP 1
#define AMP_GPIO_PERIPH RCC_APB2Periph_GPIOB
#define AMP_GPIO_GROUP GPIOB
#define AMP_GPIO_PIN GPIO_Pin_12

Все настройки в этом файле задокументированы, но мы все равно остановимся на каждой настройке.
#define DEBUG0 0
#define DEBUG1 1
#define DEBUG2 0

Если присвоить дефайну DEBUG0 единицу, то наше устройство перестанет что либо делать, кроме того, что выводить по UARTу значения, которые он получает с аудио-входов в формате, который может «переварить» SerialPortPlotter. 

Если же присвоить единицу DEBUG1, то устройство уже будет полностью функционировать, но будет выводить немного информации о работе по UARTу. Это все нужно исключительно для отладки.

Присвоение DEBUG2 даст всего лишь инициализацию UARTа. Если вы не понимаете, зачем это, то и не надо :-)
#define MaxEqualToZeroValue 3

Далее у нас параметр отвечающий значение которого или менее будет считать нулем. Как уже было ранее сказано некоторые источники звука плохого качества и сильно зашумлены.
#define MaxAvarageForNoise (float)0.4

Если аудио-канал сейчас не активен(т.е. канал, который сейчас не коммутируется на выход) и среднее значение измерений за один цикл измерений по этому каналу меньше значения этого параметра, то канал считается без звука.
#define MaxAvarageForActiveNoise (float)0.06

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

#define CountOfConsecutiveZeroValueForNoise 250

Этот параметр исключительно для оптимизации расхода процессорного времени. Если устройство встречает подряд заданное количество нулей, то оно считает, что это сигнал не звук.

#define MinCountOfZeroValue 550

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

#define USE_LED 1
#define LED_GPIO_PERIPH RCC_APB2Periph_GPIOC
#define LED_GPIO_GROUP GPIOC
#define LED_GPIO_PIN GPIO_Pin_13 #define USE_AMP 1
#define AMP_GPIO_PERIPH RCC_APB2Periph_GPIOB
#define AMP_GPIO_GROUP GPIOB
#define AMP_GPIO_PIN GPIO_Pin_12

Данный блок предельно понятен для тех, кто уже программировал микроконтроллеры. Он выбирает пин на котором будет расположен светодиод и выход на реле управления усилителем. Если Вы не будете изменять мою схему, то эти параметры Вам не нужны.

Перейдем к следующим настройкам:

Открыв файл main.cpp, в самом начале функции
int main()

вы найдете определение кучи переменных.

Остановимся на этом поподробней. Там достаточно много параметров, отвечающих за аппаратую настройку микроконтроллера. Их мы затрагивать не будем.
const uint8_t channelsCount = 2;


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

const uint8_t countOfIterationsForSwitch = 5;


Количество циклов измерения, необходимое для изменения состояния активное/пассивное.

const uint8_t ADCSampleTime = ADC_SampleTime_239Cycles5;


Этот параметр отвечает за качество измерения. Оно установлена максимальное, не рекомендую его менять
const uint16_t measurementsDuration = 2000;


Это время в ms, в течение которого будет производится один цикл измерений.

const uint32_t measurementFrequencies[] = { 1000, 1000, 1000, 1000 };


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

Заключение


Ну вот и все. Все необходимые настройки я описал. Осталось только собрать схему, скомпилировать проект, залить прошивку в микроконтроллер и радоваться.

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

AudioSwitcher — автоматизация того, что казалось бы не нужно автоматизировать Stm32, Аудиофилия, Схемотехника, Печатная плата, Микроконтроллеры, Радиолюбители, Электроника, Длиннопост

Если у вас источники звука довольно хорошие, то вы можете поставить низкие параметры настроек, но для переключения состояния звука может потребоваться его выключение (не из розетки). Возможно когда нибудь я добавлю ссылку на 3D модель корпуса, но пока у меня нет 3D принтера и корпус на данный момент такой. Но это только пока: 3D принтер уже собирается :-)

AudioSwitcher — автоматизация того, что казалось бы не нужно автоматизировать Stm32, Аудиофилия, Схемотехника, Печатная плата, Микроконтроллеры, Радиолюбители, Электроника, Длиннопост

Спасибо за прочтение.
Статья на хабре

Показать полностью 4
[моё] Stm32 Аудиофилия Схемотехника Печатная плата Микроконтроллеры Радиолюбители Электроника Длиннопост
7
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии