Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Беспроводной последовательный Bluetooth на Raspberry Pi 2 с Windows 10 IoT Core

Компоненты и материалы

Raspberry Pi 2 Model B 1
USB Bluetooth-адаптер (generic) 1
Arduino UNO 1
SparkFun Bluetooth Modem — BlueSMiRF Silver 1

Приложения и онлайн-сервисы

О проекте

Дополнительно

Этот проект подробно обсуждается на embedded101.com: «Win 10 IoT-Core: Bluetooth Universal Windows Serial App».

Описание

Это универсальное приложение Windows (UWP), которое подключает устройство IoT Core (например, Raspberry Pi 2) к встроенному Bluetooth-устройству через профиль последовательного порта (SPP) с использованием обычного USB Bluetooth-адаптера.

Предыстория

Bluetooth поддерживает одноранговую сеть на короткой дистанции. В отличие от Wi-Fi, Bluetooth-соединение — один-к-одному. Два устройства могут подключиться и взаимодействовать. Например, два устройства могут соединиться симметрично через последовательный профиль и передавать сырые данные друг другу. Однако обычно Bluetooth-соединение асимметрично: одно устройство генерирует специфический формат данных для потребления другим. Например, мобильный телефон может реализовать профиль A2DP (Advanced Audio Distribution Profile) для потоковой передачи аудио на гарнитуру, реализующую профиль HSP (Headset Profile). OBEX (Object Exchange) — симметричное соединение между двумя устройствами, обменивающимися данными.

Пример проекта Microsoft IoT-Core Bluetooth использует профиль GATT (Generic Attribute Profile). Он обеспечивает обнаружение и описание профилей для протокола Bluetooth Low Energy. С этим протоколом простые низкопотребляющие устройства могут подключаться к сложному процессору.

Этот проект намного проще примера Microsoft. Он заботится только о более общем профиле SPP (Serial Port Profile), основанном на профиле RFCOMM. Разработан с очень старым USB Bluetooth-адаптером, поэтому должен работать с любым Bluetooth-адаптером.

Приложение IoT

Это простое тестовое универсальное приложение Windows 10 для Bluetooth Serial. Оно начинает с перечисления (в виде списка) всех устройств, сопряженных по Bluetooth с устройством, где запущено приложение. Одно выбирается двойным кликом, что инициирует подключение. Текст для отправки вводится в TextBox и отправляется при нажатии кнопки. Приложение автоматически принимает любой присланный текст (и отображает его). Таким образом, когда конечная точка просто эхо-возвращает полученный текст, отправленный текст должен появиться снова в поле приема UWP-приложения.

Беспроводной последовательный Bluetooth на Raspberry Pi 2 с Windows 10 IoT Core

Конечная точка (Endpoint)

Для тестирования используется Arduino Uno с Bluetooth-адаптером. У него простой скетч, который просто эхо-возвращает любые полученные символы по Bluetooth-соединению:

Настройка шилда:

// Приложение для последовательной петли (loopback)
// После настройки
// Инициируется подключенной системой
// Можно использовать с Bluetooth, где RxTx BT-устройства
// подключены к TxRx платы Arduino.
// Необходимо отключить BT-адаптер для прошивки.
void setup() {
  // Мой адаптер настроен на этот BAUD 115200
  // Это скорость порта Arduino -> BT-адаптер
  // Устанавливается, когда BT-адаптер в командном режиме.
  // Это НЕ скорость BT, которую нельзя изменить.
  Serial.begin(115200);
  delay(333);
  while (!Serial) ;
  delay(1000);
  Serial.println("The quick brown fox jumps over the lazy dog!");
}

Цикл шилда:

void loop() {
  char ch = Serial.read();
  while ( 255 == (byte) ch) {
    ch = Serial.read();
  }
  Serial.print(ch);
}

Сопряжение (Pairing)

Bluetooth — сценарий одноранговой сети. Прежде чем подключиться по Bluetooth, устройства должны быть сопряжены. Это не делается внутри приложения. Сопряжение с кодом доступа может быть проблематичным между встроенными устройствами, так как они часто безголовые (headless) и могут не поддерживать всплывающие окна (как IoT Core). Для этого есть веб-портал IoT Core, а также утилита командной строки на устройстве, которую можно запустить через SSH. Последняя версия веб-портала ОС поддерживает сопряжение с кодом доступа, чего не было во время Windows 10 RTM. Статья «Win 10 IoT-Core: Bluetooth Universal Windows Serial App» подробно обсуждает сопряжение в этом контексте.

Начало проекта

Проект приложения создается в Visual Studio 2015 с использованием шаблона Universal Windows App:

New Project → Visual C# → Windows → Blank App (Universal Windows)

Создание UI приложения

UI реализован в XAML. Создайте UI согласно макету выше (или похожему):

Вы можете предпочесть Relative StackPanels или Grid с рядами и колонками.

ConnectDevices — это ListBox с Binding Source, установленным на PairedDevices (см. ниже) и ItemTemplate, состоящим из TextBlock, привязанного к свойству Name объекта PairedDevices (см. ниже).

<ListBox x:Name="ConnectDevices" ItemsSource="{Binding Source={StaticResource PairedDevices}}" Margin="10" DoubleTapped="ConnectDevices_DoubleTapped" Width="Auto" Height="Auto">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding Name}" />
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

Конфигурация приложения

Измените секцию Capabilities (внизу) на:

<Capabilities>
  <Capability Name="internetClient" />
  <DeviceCapability Name="bluetooth.rfcomm">
    <Device Id="any">
      <Function Type="name:serialPort"/>
    </Device>
  </DeviceCapability>
</Capabilities>

Возможность internetClient уже будет там. Она не нужна для этого приложения, можно удалить. Я оставляю.

Информация о сопряженных устройствах (PairedDevice Information)

При запуске приложения сопряженные устройства перечисляются с помощью:

DeviceInformationCollection DeviceInfoCollection
  = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));

Эта коллекция затем превращается в ObservableCollection для использования в ListBox:

_pairedDevices = new ObservableCollection<PairedDeviceInfo>();

Коллекция DeviceInfoCollection перебирается, создавая объект PairedDeviceInfo для каждого элемента, который добавляется в _pairedDevices.

PairedDeviceInfo — класс со свойствами:

Name <string>
Id <string>
DeviceInfo <DeviceInformation>

Класс имеет соответствующий конструктор.

DeviceInformation — это Windows.Devices.Enumeration.DeviceInformation.

В списке сопряженных устройств отображается (привязано) поле Name.

Когда устройство выбрано (двойной клик), DeviceInformation конечной точки фактически является частью выбранного элемента меню и используется для установления соединения.

Подключение (Connection)

DeviceInformation используется для получения RFCOMM-сервиса. Соединение устанавливается как StreamSocket, используя HostName конечной точки (фактически её Bluetooth MAC-адрес) и строку ServiceName.

_service = await RfcommDeviceService.FromIdAsync(DeviceInfo.Id);
_socket = new StreamSocket();
await _socket.ConnectAsync(_service.ConnectionHostName, _service.ConnectionServiceName);

Если всё хорошо — у нас есть соединение, сокет значим (не null).

Конечно, это обернуто в обработку ошибок (try-catch).

Отправка и прием текста используют свойства InputStream и OutputStream сокета.

Прием текста (Receive Text)

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

private async void Listen() {
  ReadCancellationTokenSource = new CancellationTokenSource();
  if (_socket.InputStream != null) {
    dataReaderObject = new DataReader(_socket.InputStream);
    // продолжаем чтение последовательного ввода
    while (true) {
      await ReadAsync(ReadCancellationTokenSource.Token);
    }
  }
}
DataReader dataReaderObject;
private CancellationTokenSource ReadCancellationTokenSource;
private async Task ReadAsync(CancellationToken cancellationToken) {
  uint ReadBufferLength = 1024;
  // Если запрошена отмена задачи — подчиняемся
  cancellationToken.ThrowIfCancellationRequested();
  // Устанавливаем InputStreamOptions для завершения асинхронной операции чтения,
  // когда доступен один или более байт
  dataReaderObject.InputStreamOptions = InputStreamOptions.Partial;
  // Создаем задачу для ожидания данных на serialPort.InputStream
  var loadAsyncTask = dataReaderObject.LoadAsync(ReadBufferLength).AsTask(cancellationToken);
  // Запускаем задачу и ждем
  UInt32 bytesRead = await loadAsyncTask;
  if (bytesRead > 0) {
    string recvdtxt = dataReaderObject.ReadString(bytesRead);
  }
}

Отправка текста (Send Text)

Пока прием текста выполняется асинхронно (приход текста недетерминирован с точки зрения приложения), отправка текста инициируется из UI приложения и поэтому по сути синхронна (хотя используется await для освобождения UI).

private async void Send(string msg) {
  Task storeAsyncTask;
  DataWriter dataWriteObject = new DataWriter(_socket.OutputStream);
  dataWriteObject.WriteString(msg);
  // Запускаем асинхронную задачу для завершения операции записи
  storeAsyncTask = dataWriteObject.StoreAsync().AsTask();
  UInt32 bytesWritten = await storeAsyncTask;
}

Состояния кнопок (Button States)

Командные кнопки включаются и отключаются в зависимости от состояния приложения. Например, кнопки Send и Start Recv отключены, когда приложение не подключено, но становятся активными при подключении и т.д.

Наслаждайтесь! :)

Производственный процесс

  1. Расширение GoPiGo v2 на Windows 10 IoT Core для Raspberry Pi 3
  2. Управление яркостью LED с ШИМ через кнопку на Arduino Mega
  3. Устройство точного измерения давления и расхода воздуха на аналоговом датчике
  4. Создание игры в реальном времени на Arduino Nano с гироскопом MPU-6050 и OLED-дисплеем
  5. Камера охраны с детектором движения на ESP32-CAM и отправкой фото в Discord
  6. Проект с датчиком DHT11: индикация температуры светодиодами и пьезо-динамиком на Arduino
  7. Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live
  8. Самодельный пульт от ТВ на Arduino с 3D-корпусом и питанием от батарейки
  9. Управление светодиодом по Bluetooth с Arduino: простой DIY-гид
  10. Простой ИК-датчик препятствий на Arduino: ИК-светодиод и фотодиод