Pull to refresh

Разработка своего первого USB устройства. Маленький шаг вперед

DIY
Давным-давно уже бредил мечтой собрать какое-нибудь устройство, пусть незамысловатое, но которое бы выполняло определенные действия под управлением компьютера. По профессии я web-разработчик, опыта в программировании микроконтроллеров никакого, но тема интересная. Навыков пайки тоже мало (ну наушники или проводки разные могу спаять конечно, но чипы паять не пробовал). Поэтому решил, что начинать необходимо с чего-то простого — например на основе уже готовой макетной платы с микроконтроллером. 

Что будет в посте?

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



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

Поиск информации


В поисках информации помогла статья на Хабре, Управление самодельным USB-HID светодиодом, c помощью GUI оболочки на .NET. В этом посте автор рассказывает о покупке небольшой отладочной платы AVR-USB-TINY45. Прошел по ссылкам автора и обнаружил там несколько готовых отладочных плат. AVR-USB-TINY45, которую использовал автор вышеупомянутого поста, для моих опытов было недостаточно, а AVR-USB162 была для меня слишком крута (библиотека LUFA сложновата, и примеров ПО хоста я чего-то не нашел), поэтому мой выбор остановился на плате AVR-USB-MEGA16 с микроконтроллером ATmega32 на борту.

Подробнее о покупке


Покупка отладочной платы AVR-USB-MEGA16 вместе с доставкой и всеми процентами за перевод средств по Webmoney (оказалось, что пополнить Yandex-Деньги у нас в Харькове не так-то просто) обошлась мне ~26 USD. Доставка из Москвы в Харьков была немного затянута (посылка застряла где-то под Харьковом), но все вскоре пришло. Хочется сказать отдельное спасибо microsin.ru — плата была надежно упакована и защищена от ударов.

Схема отладочной платы AVR-USB-MEGA16

Схема отладочной платы AVR-USB-MEGA16

Подробного описания платы здесь не будет (кому интересно, см. ссылки). Скажу только, что на плате уже имеется вся необходимая обвязка для микроконтроллера и USB — т. е. можно воткнуть плату в USB, она будет от него питаться и микроконтроллер ATmega32 заработает. Нужно только написать для него программу (об этом далее), и напаять на макетное поле платы (8x11 с шагом между отверстиями 2.54 мм) какую-нибудь конструкцию. На плате имеется 22 свободных порта ввода/вывода (выведенные на два ряда отверстий), на которые мы можем повесить светодиоды.

Так же очень важной оказалось возможность прошивки микроконтроллера на плате с помощью USB. Да, никаких программаторов не нужно, только USB, так как в ATmega32 уже вшит USB загрузчик программы (как с ним работать, написано на Хабре, см. ссылки). Для программирования и отладки также можно использовать интерфейсы ISP и JTAG, но мне это не понадобилось, так как пока ни программатора, ни внутрисхемного отладчика у меня нет.

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


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

Сборка


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



Еще мне понадобилась дополнительная дешевая макетная плата (которую не жалко портить паяльником при моих первых опытах пайки), которую я вместе со всей необходимой мелочевкой купил на радиорынке:



Далее дело было не хитрое — напаять светодиоды и резисторы к ним. Первый раз сталкиваясь с необходимостью работы со светодиодами, перелопатил много информации, чтобы понять как это все работает. Всю необходимую информацию я нашел на сайте easyelectronics.ru, где подробно было расписано «как и что». Огромное им спасибо.

В итоге у меня получилось что-то такое (на плату напаял коннектор и несложную схему соединения светодиодов с решеткой и общим минусом):



Две платы друг с другом решил соединить с помощью шлейфа от старого компьютера:



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

Программная часть


Общение

Здесь стоит заметить, что сама плата, к сожалению, а может и к радости, не имеет встроенного USB интерфейса, по этому все общение компьютера с платой осуществляется с помощью библиотеки V-USB, разработанной компанией Objective Development Software, которая распространяется по лицензии GPL.
Для компьютера используется библиотека libusb-win32 для операционной системы Windows (2000, 2003, XP) и libusb для операционных систем семейства *nix (Mac OS, Linux и т. д.).

Прошивка

Такая важная часть проекта, как прошивка… Хотелось вновь таки, чего-нибудь простого, но эффективного.
Мне почему-то очень везло в то время с поиском информации и поэтому все там же, на вышеупомянутом сайте, я нашел отличное решение: прошивку для МК, а также класс-обертку, написанную на C# (наиболее дружелюбный мне язык программирования для Windows).

Сама прошивка написана таким образом, что основная ее задача это установить бит в определенном регистре, с помощью данных, полученных посредством USB. Всем остальным занимается desktop программа.

Программа

Все, что нужно было сделать дальше это написать программу, которая бы отсылала нужные биты в нужные регистры, используя вышеупомянутую обертку для C#. Это уже не должно составлять никакого труда, тем более все, что нужно от программы это получить текущий уровень громкости в системе и изменить нужный бит.

Немного порыскав в старых папках, была отыскана какая-то не нужная подходящая заготовка, спрятанная для будущих нужд ранее, написанная на основе AudioCoreApi (C#).



Что ж, осталось расставить нужные команды в нужных событиях.

Так как я подключил светодиоды на плате ко всем ногам порта A микроконтроллера, то соответственно «дергать» ногами МК мне нужно в соответствии со светодиодами. Состояние каждого светодиода соответствует состоянию каждого бита в байте PORTA (байт, который отвечает за состояние ног мк на порте А).

Находим главный таймер в программе и пишем такой код:
byte PortState = 0;
for (int i = 1; i <= 8; ++i)
{
   if (leftVolumeLevelPercent > 12 * i) 
   {
      PortState <<= 1;
      PortState |= 0x01;
   }
}
hundler.PORTA = PortState;

Здесь, в зависимости от уровня громкости в системе, мы с помощью операций сдвига, устанавливаем, либо сбрасываем определенный бит в hundler.PORTA, где hundler является объектом для работы с устройством, а PORTA — байтом порта ввода/вывода, реализуемым следующим образом:

public byte PORTA 
{
  set
    {
      usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
                                RQ_IO_WRITE, value, aPORTA, null, 0, 5000);
            }
            get
            {
                usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
                                RQ_IO_READ, 0, aPORTA, buffer, 1, 5000);

                return buffer[0];
            }
        }

Функция usb_control_msg() является функцией из библиотеки V-USB.

Также важным моментом является то, что перед использованием порта А, все его ноги нужно установить на вывод, а не на ввод (Говоря честно, нечаянно пропустив этот момент в некоторых статьях, он немного сбил меня с толку, когда светодиоды горели в треть силы) следующим образом:

hundler.DDRA = 0xFF; // Ну или что-то вместо 255, смотря сколько ног вы хотите поставить на вывод


Ну вот, собственно, и все! Спасибо, что дочитали до этого момента. Надеюсь в комментариях не будет разговоров о картинке «как нарисовать сову», вроде все понятно и не очень уж сложно как мне казалось ранее. Также, не хотел этого говорить, но это уже пол пути к лампе настроения :)

Видео





Ссылки

  1. Управление самодельным USB-HID светодиодом, c помощью GUI оболочки на .NET
  2. Описание отладочной платы AVR-USB-MEGA16
  3. Прошивка и класс обертка на C#
  4. Программа на C# из поста

P.s. Прошу прощения за некачественные фотографии и видео. К сожалению, ничего под рукой кроме гуглофона не оказалось.
Tags:
Hubs:
Total votes 117: ↑113 and ↓4 +109
Views 34K
Comments Comments 35