Windows Remote Arduino — управляем настольной лампой прямо из универсального приложения Windows

Завершая неделю интернета вещей на хабре и в продолжение предыдущего поста о партнерстве с Arduino, расскажу вам о подключении устройств к Windows. Я уже писал про различные сценарии подключения датчиков к облаку, но бывают сценарии, когда нам хочется просто подключить датчики или устройства к нашему компьютеру и удаленно ими управлять. Например, мы хотим сделать приложение, которое будет включать и выключать настольную лампу. В этих случаях самым простым решение будет использование Windows Remote Arduino.


Что такое Windows Remote Arduino


Windows Remote Arduino — это библиотека WinRT, которая позволяет управлять цифровыми и аналоговыми каналами платы Arduino из Windows/Windows Phone приложения, с помощью привычных команд типа digitalRead/Write и analogRead/Write. При этом сама плата может быть подключена к компьютеру по USB или Bluetooth — важно, чтобы обеспечивался последовательный канал передачи данных. Помимо простых команд включения/выключения входов/выходов, в том или ином виде предусмотрена работа с шиной I2C и (в перспективе) сервоприводами.

bd37c1e07a2448668764fcaaf3fbe40e.png

Для работы необходимо, чтобы на плате Arduino была запущена специальная программа, поддерживающая выполнение команд по протоколу Firmata. Библиотека Windows Remote Arduino обменивается командами с платой, предоставляя программисту высокоуровневые функции управления.

Windows Remote Arduino доступна для Windows 8.1/Windows Phone 8.1 и для универсальных приложений Windows 10. Чтобы использовать их в своем проекте, в настоящее время проще всего клонировать Git-репозиторий проекта и добавить необходимые проекты в своё решение (пример я опишу ниже).

Пример — включатель лампочки


В моём примере я буду разрабатывать интеллектуальное приложение, включающее настольную лампу. Для этой цели я использую плату Arduino Uno и реле, способное коммутировать 220В. Реле подключается к какому-нибудь цифровому выходу (например, 7). Также для обнаружения присутствия человека будем использовать инфракрасный датчик присутствия, который включим в аналоговый вход A0. Для удобства коммутации мы используем Troyka Shiled от Амперки. На приведенном выше видео смотрите подробнее про hardware setup, а также весь проект в действиии.

Устанавливаем скетч Firmata на плату Arduino


Первым делом необходимо установить на плату Arduino стандартный скетч для выполнения команд Firmata. Такой скетч уже включен в стандартную поставку Arduino IDE — достаточно выбрать в меню File –> Examples –> Firmata –> Standard Firmata. Открывшийся при этом скетч необходимо загрузить в плату обычным образом.

6035eeb69307410ea676617b8db7c39b.png

На этом этапе полезно будет убедиться, что все аппаратное обеспечение настроено правильно. Для этого можно использовать специальную программу firmata_test.exe (или любую из программ, описанных здесь) — вы должны быть в состоянии управлять лампочкой, переключая состояние цифрового выхода 7, а также на входе A0 вы должны получать значение 0, если движения вокруг сенсора нет, и большое положительное значение (около 600 и более) в противном

8a3f1421d6244d1780ca9c5a0df6b137.png626b83b12aba407a8974be84d880dd48.png

Готовим проект с Windows Remote Ardunio


Чтобы использовать Windows Remote Arduino в своём проекте, необходимо подключить соответствующие библиотеки. На текущий момент технология достаточно молодая, и библиотеки существуют в виде исходных текстов. Мы надеемся, что со временем появятся пакеты NuGet, сейчас же процесс включения библиотек выглядит следующим образом:

  1. Создайте новый проект — в нашем случае это будет универсальное приложение Windows 10
  2. Клонируйте GitHub-репозиторий проекта Windows Remote Arduino в какую-нибудь локальную папку:
    git clone https://github.com/ms-iot/remote-wiring/
    
    

    ВАЖНО: в репозитории имеются несколько версий библиотеки. На момент написания статьи последняя ветка master содержала много ошибок при работе с аналоговыми и цифровыми входами, поэтому я использовать наиболее стабильную ветку revert-18-develop. Очень надеюсь, что в скором времени выйдет еще более стабильная версия, и клонировать можно будет как показано выше, без указания ветки.
  3. В получившемся дереве проектов есть папки Microsoft.Maker.Win10 и Microsoft.Maker.Win8_1. Мы будем использовать вариант для Windows 10, но проект поддерживает и универсальные приложения Windows 8.1
  4. В папке Microsoft.Maker.Win10 есть три проекта: Microsoft.Maker.Firmata, Microsoft.Maker.Serial и Microsoft.Maker.RemoteWiring. Эти три проекта нужно добавить в созданный нами проект (Add Existing Project)
  5. В результате получится следующее дерево проектов:
    0d50f7b9a95b459eaf8fbab8b65f680d.pngfa6e40b2b7784392a3f033ffb80a4ffe.png
  6. Чтобы проекты компилировались в правильном порядке, необходимо установить правильные зависимости проектов. Нажмите правой кнопкой на наш проект, выберите «Зависимости сборки –> Зависимости проектов», и установите галочки напротив всех трех добавленных проектов. Остальные зависимости должны быть уже установлены, но вы можете их проверить: проект Firmata зависит от проекта Serial, проект RemoteWiring — от проектов Firmata и Serial. Соответственно, на вкладке «Порядок сборки» проекты должны собираться в таком порядке: Serial, Firmata, RemoteWiring и наше приложение.
  7. В нашем основном проекте правой кнопкой нажмите на References и добавьте расширение Microsoft Visual C++ AppLocal Runtime Package for Windows UAP. Там же в пункте «Общие проекты» выберите все три добавленных проекта Windows Remote Arduino.
    542f52d8cb184d7aabcd6dff39265bfe.png
  8. ВАЖНО: Чтобы наше приложение могло использовать возможности работы с последовательным портом, необходимо в манифест приложения (файл Package.appxmanifest) в раздел
    
    
    добавить следующий код:
    
       
          
       
    
    
    

  9. Мы готовы к созданию нашего приложения, которое будет использовать библиотеки Windows Remote Arduino! Чтобы убедиться, что всё работает правильно, попробуйте выполнить сборку получившегося приложения.

Создаем приложение с Windows Remote Arduino


Наше приложение будет иметь три кнопки: для включения лампочки, для выключения, и для авто-режима, в котором лампочка будет управляться датчиком присутствия. Для начала добавим на главную страницу приложения MainPage.xaml эти три кнопки, установив их в неактивное состояние:

        
            
            
            
            
            
        


Этот код добавляется внутрь того контейнера Grid, который уже по умолчанию есть у страницы. Также для каждой кнопки создадим функцию-обработчик на C# (кликнув дважды на каждую кнопку, или через окно свойств Visual Studio).

Для начала инициализируем объект Remote Arduino. Для этого в классе окна в файле MainPage.xaml.cs опишем две переменные:

UsbSerial usbcomm;
RemoteDevice arduino;


Для подключение к Arduino опишем функцию connect (), которую затем вызовем из конструктора MainPage ():

private async void connect()
{
    var dev = await UsbSerial.listAvailableDevicesAsync();
    usbcomm = new UsbSerial(dev[0]);
    arduino = new RemoteDevice(usbcomm);
    usbcomm.ConnectionEstablished += Comm_ConnectionEstablished;
    usbcomm.begin(57600, SerialConfig.SERIAL_8N1);
}


Здесь мы сначала определяем список доступных портов, куда может быть подключен Arduino, затем создаем последовательное соединение UsbSerial с этим портом, а затем поверх этого — объект RemoteDevice, который будет представлять собой виртуальный Arduino. После этого мы вызываем функцию begin, передавая параметры последовательного соединения.

ВАЖНО: Скорость последовательного канала, используемая протоколом Firmatа, задается в скетче StandardFirmata. По умолчанию она равна 57600, поэтому мы выбираем именно эту скорость в нашем приложении. Если скорости не будут совпадать, то соединение не будет работать.

При установлении соединения с платой, будет вызвана функция Comm_ConnectionEstablished, которую мы опишем следующим образом:

private void Comm_ConnectionEstablished()
{
    Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,new Windows.UI.Core.DispatchedHandler(() =>
    {
        arduino.pinMode(14, PinMode.ANALOG);
        arduino.pinMode(relay_pin, PinMode.OUTPUT);
        dt = new DispatcherTimer() { Interval = new TimeSpan(500) };
        dt.Tick += loop;
        dt.Start();
        on.IsEnabled = true;
        off.IsEnabled = true;
        auto.IsEnabled = true;
    }));
}


Основной код функции обернут в вызов диспетчера, который запускает его в потоке UI — это важно. Далее мы устанавливаем режимы основных используемых пинов Arduino, создаем таймер, который будет вызывать каждые пол-секунды функцию loop (), а также делаем кнопки видимыми.

Интересный момент — установка порта 14 в аналоговый режим. Дело в том, что аналоговые входы в Arduino нумеруются после цифровых, и входу A0 соответствует номер 14. Режим необходимо установить именно ANALOG, а не INPUT, который означает цифровой ввод.

Теперь для включения/выключения лампочки достаточно описать функции-обработчики событий кнопок следующим образом:

private void on_Click(object sender, RoutedEventArgs e)
{
    auto_mode = false;
    arduino.digitalWrite(relay_pin, PinState.HIGH);
}


Функция off_Click делается по аналогии. Обратите внимание, что для работы с пинами удалённой платы Arduino используются привычные команды типа digitalRead/digitalWrite.

Переменная auto_mode — это переменная типа bool, которую нужно описать в нашем классе. Она нужна для того, чтобы обрабатывать автоматический режим. Кнопка AUTO будет устанавливать эту переменную в true:

private void auto_Click(object sender, RoutedEventArgs e)
{
    auto_mode = true;
}


Теперь дело осталось за малым — реализовать функцию loop, которая будет переключать лампу в зависимости от наличия сигнала с датчика присутствия. Делать это надо только в том случае, если auto_mode установлен:

private void loop(object sender, object e)
{
    if (auto_mode)
    {
        arduino.pinMode(14, PinMode.ANALOG);
        var on = arduino.analogRead(0) > 512;
        arduino.digitalWrite(relay_pin, on ? PinState.HIGH : PinState.LOW);
    }
}


ВАЖНО: Для более надежной работы прямо перед чтением порта лучше еще раз установить его режим в аналоговый. Так быть не должно, но на практике это улучшает стабильность. Также обратите внимание, что мы используем analogRead (0), хотя строчкой ранее указывали номер порта 14. В analogRead передается номер порта от 0 до 5, при установке режима порта надо прибавить к этим номерам 14.

Как подключить Arduino по Bluetooth и управлять со смартфона


В нашем случае мы написали универсальное приложение, которое можем разместить на Windows Phone 10. Однако это бесполезно, поскольку подключить плату Arduino по USB к смартфону невозможно. Однако если мы будем использовать Bluetooth вместо USB-соединения, подключив к Arduino bluetooth-плату, то мы сможем этим же приложением управлять нашей конструкцией со смартфона. В этом случае в манифест приложения необходимо добавить следующие строчки для разрешения коммуникации по Bluetooth:


  
    
  



Мы не будем сейчас рассматривать использование bluetooth — это тема для отдельной статьи. Однако заметим, что с точки зрения программирования разницы почти нет — надо использовать объект BluetoothSerial вместо UsbSerial, а все остальные конструкции остаются без изменений.

Где взять исходный код


Исходный код моего проекта по традиции доступен на GitHub: https://github.com/evangelism/RemoteArduinoLamp/tree/v1.0-serial. Пожалуйста, берите его, экспериментируйте, если найдете ошибки — делайте pull requests.

Выводы


Windows Remote Arduino — достаточно молодая и сырая технология, но уже сейчас она может упростить решения ряда задач, в которых необходимо напрямую управлять входами/выходами платы Arduino, подключенной к компьютеру. Конечно, всё тоже самое можно запрограммировать вручную, написав свой скетч и используя последовательный канал для взаимодействия с ним, но почему бы не использовать уже готовые наработки и сложившиеся стандарты (Firmata), чтобы не изобретать велосипеды.

Я надеюсь, вы будете использовать Windows Remote Arduino в своих проектах, и если вы сделаете что-то интересное — мне будет приятно об этом узнать! Пишите в комментариях, в твиттере или вконтакте!

© Habrahabr.ru