Управление Arduino Rover с помощью Firmata и контроллера Xbox One
Компоненты и расходные материалы
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
Приложения и онлайн-сервисы
|
Об этом проекте
Несколько месяцев назад я купил маленький вездеход (управляемый Arduino Uno) по очень хорошей цене. Набор был очень полным:автомобильное шасси, 2 автомобильных колеса, 2 мотор-редуктора постоянного тока, UNO R3, двойной H-мостовой контроллер двигателя L298N и несколько других компонентов.
Этот марсоход предназначен для автономной работы. Следовательно, в комплект также добавляются ультразвуковой датчик и сервопривод. Также в комплекте хороший сенсорный экран 5 Arduino. Да, это была выгодная сделка;-)
Но моя идея заключалась в том, чтобы использовать как контроллер Xbox One, так и протокол Firmata, чтобы управлять им один или один из моих сыновей. И работает очень хорошо!
Вот видео окончательного решения:
В этом проекте используются следующие основные части:
- Комплект ровера (для этой демонстрации мы используем только часть деталей:опорную пластину, колеса, двигатели, Arduino Uno, держатель батареи на 9 В и контроллер двигателя L298N с двойным мостом H-Bridge)
- Дополнительный батарейный отсек для 6 батареек AA.
- Модуль Bluetooth (HC-06)
- Контроллер Xbox One с беспроводным адаптером для Windows (для подключения к ноутбуку)
- Ноутбук (с Windows 10 + VS2015 + адаптер Bluetooth)
- Мигающий свет только для драматического эффекта.
Сборка комплекта
Собрать комплект не так уж и сложно. Хотя инструкция по сборке была на китайском языке, все кажется довольно логичным. Опорная плита только одна, поэтому мне пришлось положить некоторые компоненты сверху, а некоторые - снизу (теперь контроллер мотора):
На этом изображении добавлены два разных держателя батарей. Во время программирования я обнаружил, что мне нужно использовать отдельный источник питания только для запуска двигателей.
Подключение двигателей - разводка контактов контроллера
На этот раз самое главное оборудование - это не Arduino Uno, а контроллер двигателя.
«L298 - это двойной H-мостовой драйвер для щеточных двигателей постоянного тока и шаговых двигателей. Он поддерживает широкий диапазон рабочих напряжений и может выдавать 2 А на канал в сквозном корпусе, доступном для самостоятельных проектов ».
Этот контроллер будет управлять скоростью и направлением каждого из двух двигателей, используя сигналы, поступающие от Arduino.
Схема расположения контактов двойного H-мостового контроллера двигателя L298N:
- Плюс + двигателя постоянного тока 1
- Минус - двигателя постоянного тока 1
- Включение питания. Я питаю 9 вольт от отдельного батарейного отсека.
- Общие точки соприкосновения. Подключен как к моему отдельному держателю батареи, так и к Arduino.
- Отключение . Может выдавать 5 вольт ( не используется . Моя Arduino получает питание от другого держателя батареи)
- ENA подключена к Arduino D10. Этот порт поддерживает ШИМ (белый цвет)
- IN1 подключен к Arduino D9. (серый)
- IN2 подключен к Arduino D8. (фиолетовый)
- IN3 подключен к Arduino D7. (синий)
- IN4 подключен к Arduino D6. (зеленый)
- ENB подключен к Arduino D5. Этот порт поддерживает ШИМ (желтый)
- Плюс + двигателя постоянного тока 2
- Минус - двигателя постоянного тока 2
- Перемычка рядом с цифрами 2 и 3 НЕ удаляется потому что я не превышаю входную мощность более 12 вольт (до 35 вольт) (перемычка не отмечена на картинке)
Примечание:контроллер имеет собственный источник питания. У Arduino тоже есть. Чтобы все работало, дайте им общий язык . См. Пункт 4 выше)
Подключение двигателей - схема контактов Arduino
Подключить Arduino довольно просто. Подключаем землю и 5 вольт блока питания к Arduino. И мы подключаем шесть линий (ENA, IN1-4 и ENB) к контактам с D10 по D5.
Должно быть ясно, что порты 7 и 8 (а также 9 и 10 для другого двигателя) являются обычным портом GPIO. Они будут использоваться для направления двигателя. Если оба порта (например, 7 и 8) в НИЗКОМ состоянии, двигатель ничего не сделает (остановится). Если один ВЫСОКИЙ, а другой НИЗКИЙ, двигатель будет вращаться в одном направлении. При обратном подключении (первый установлен на НИЗКИЙ, а другой - на ВЫСОКИЙ), подключенный двигатель будет работать в другом направлении.
Но .. просто установка этих контактов ни к чему не приведет. Пока нет движущихся частей!
Магия будет исходить от контактов 5 и 10. Это «специальные» контакты, которые могут генерировать сигнал ШИМ. Установка значения от 0 до 255 приведет к работе двигателя ОЧЕНЬ медленно (остановлен) или на высокой скорости.
Примечание. Каждый порт Arduino Uno, поддерживающий ШИМ, отмечен тильдой (~).
Подключение Bluetooth
Модуль Bluetooth, который я использую, нужно подключить только к портам RX и TX (пересекайте линии), и ему требуется питание 5 В и заземление от Arduino.
Скетч фирмы на Arduino
Скетч Firmata StandardFirmata - это все, что нам нужно на Arduino! Просто возьмите его из примеров Arduino IDE и загрузите (возможно, вам нужно сначала открепить TX / RX, чтобы завершить загрузку).
Примечание:из-за низкого качества моего модуля Bluetooth я всегда снижаю скорость передачи, которая жестко запрограммирована внутри скетча, и устанавливаю ее на 9600.
Господа, заводите двигатели
Или проверьте соединение…
Так почему я использую Firmata? потому что это легко. Как легко? Очень просто. И это можно сделать даже без программирования. Просто запустите приложение Windows Remote Arduino Experience (доступно в магазине и также работает на устройстве с Windows 10 Mobile).
Сначала вам нужно будет подключиться к уже спаренному Bluetooth-модулю HC-6.
После сопряжения перейдите на страницу ШИМ. Включите цифровой вывод 5 и присвойте ему значение, скажем, 128.
Осторожно:на следующем шаге ваш мотор заработает. Надевайте шлем и снимайте муку. Вы поймете почему, когда увидите это.
Затем перейдите на цифровую страницу. И нажмите переключатель цифрового контакта 6.
Теперь, если все подключено и работает, один из двигателей будет вращаться!
Если это так, вы можете проверить другие скорости (используя более высокое или меньшее значение ШИМ) или изменить направление (установите цифровой вывод 6 на 0 В, а цифровой вывод 7 на 5 В).
Вот и все. Вы можете управлять этим колесом!
Но это еще не все, то же самое касается контакта 10 (ШИМ), цифрового контакта 9 и цифрового контакта 8.
Оба колеса ходят. Теперь приступим к кодированию…
Приложение UWP как средство поиска матчей
Должно быть ясно, что нам нужно новое приложение UWP между контроллером Xbox One и ровером.
Я уже писал здесь об использовании контроллера Xbox One. На этот раз мы объединим эти знания с нашим вездеходом.
Давайте посмотрим на интерфейс нашего приложения UWP:
Довольно уныло, две кнопки и текстовый блок. Мне больше нечего будет делать, кроме как сначала подключиться к Arduino с помощью Firmata. И как только соединение будет установлено, кнопка контроллера должна будет запустить один гигантский цикл, чтобы прочитать ввод контроллера и преобразовать его в полезные команды.
И мы хотим создать это классическое управление танком с двумя ручками. Все, что нам нужно, это проверить два стика на контроллере Xbox One. Перемещение их вперед и назад также запустит соответствующий двигатель вперед и назад:
Примечание. Если вы запустите новое приложение UWP, не забудьте добавить возможность Bluetooth. И вам нужно будет установить пакет nuget для Firmata.
Сначала мы добавляем фрагмент XAML (см. Раздел кода для исходного кода Xaml) в сетку основной формы, чтобы у нас было несколько кнопок.
Затем мы добавляем код (см. Раздел кода для исходного кода C #) основной формы. Я в основном разделен на две части. Сначала мы устанавливаем соединение через Bluetooth с протоколом Firmata. Затем мы начинаем прослушивать ввод на контроллере Xbox One.
В цикле проверки элементов управления мы решаем, направлен ли ползунок вперед или назад или находится в диапазоне «стоп». После этого мы решаем, какое значение будет у вывода ШИМ.
Интересно видеть, что запись значения ШИМ представлена в Firmata как запись аналогового значения в цифровой порт. В классе Arduino нет специального метода ШИМ.
Я добавил два метода «ArduinoDigitalWrite» и «ArduinoAnalogWrite», чтобы предотвратить повторную запись одного и того же значения в Arduino. Это загромождает связь и снижает производительность Arduino. (В гораздо более богатой конструкции я добавил зуммер. Без игнорирования повторяющихся команд работа зуммера была очень плохой и ужасно слышной).
Когда двигатели получают низкие импульсы PMW, двигатель не запускается напрямую, он будет завывать с очень характерным звуком. Это нормальное поведение. Так я узнал, что мне нужно добавить два источника питания. Первый раз все подключил, подумал, что контроллер сломался. Ничего не случилось. Пока я не отключил один из двигателей, и другой не начал скулить.
Вот как это работает:
Сноска:мигающий свет не только для драматического эффекта. Помните о безопасности, когда ваши творения приходят в движение. Эта штуковина тупая, а вы нет! Поэтому я изначально поставил этот свет поверх него.
Код
- Элементы управления Xaml для начала взаимодействия
- Внутренний код основной формы приложения UWP.
Элементы управления Xaml для запуска обмена сниппетов
Вставьте это в основную форму вашего нового приложения UWPВнутренний код основной формы приложения UWP C #
Этот код подключается к роверу с помощью Firmata и передает команды контроллера Xbox Oneпубличный запечатанный частичный класс MainPage:Page {private BluetoothSerial _bluetooth; частный RemoteDevice _arduino; частный UwpFirmata _firmata =null; частный геймпад _Gamepad =null; // Мы никогда не предоставляем ШИМ больше 255 * 0,75 private double _SpeedLimit =0.75; // значения ниже этого абсолютного значения останавливают ровер private double _ActionPoint =0.15; закрытый байт _LeftForward =6; закрытый байт _LeftBackward =7; закрытый байт _LeftValue =5; закрытый байт _RightForward =9; закрытый байт _RightBackward =8; закрытый байт _RightValue =10; частный словарь_CurrentPinStates =new Dictionary (); частный словарь _CurrentSpeedValues =new Dictionary (); общедоступная MainPage () {this.InitializeComponent (); } private void btnStart_Click (отправитель объекта, RoutedEventArgs e) {btnStart.IsEnabled =false; Gamepad.GamepadAdded + =Gamepad_GamepadAdded; Gamepad.GamepadRemoved + =Gamepad_GamepadRemoved; _bluetooth =новый BluetoothSerial ("HC-06"); _bluetooth.ConnectionLost + =BluetoothConnectionLost; _bluetooth.ConnectionFailed + =BluetoothConnectionFailed; _bluetooth.ConnectionEstablished + =OnConnectionEstablished; _firmata =новый UwpFirmata (); _arduino =новое удаленное устройство (_firmata); _firmata.begin (_bluetooth); _bluetooth.begin (9600, SerialConfig.SERIAL_8N1); _arduino.DeviceReady + =ArduinoDeviceReady; } private async void BluetoothConnectionLost (строковое сообщение) {ожидание Dispatcher.RunAsync (CoreDispatcherPriority.Normal, () => {tbRead.Text ="ConnectionLost" + message; btnStart.IsEnabled =true;}); } private async void BluetoothConnectionFailed (строковое сообщение) {ожидание Dispatcher.RunAsync (CoreDispatcherPriority.Normal, () => {tbRead.Text ="ConnectionFailed" + message; btnStart.IsEnabled =true;}); } private async void ArduinoDeviceReady () {ожидание Dispatcher.RunAsync (CoreDispatcherPriority.Normal, () => {tbRead.Text ="Устройство готово";}); } private void OnConnectionEstablished () {var action =Dispatcher.RunAsync (CoreDispatcherPriority.Normal, new DispatchedHandler (() => {DisableEnableButtons (true); ArduinoDigitalWrite (_LeftForward, PinStateLOW); (_RightBackward, PinState.LOW); ArduinoDigitalWrite (_RightForward, PinState.LOW);})); } private void DisableEnableButtons (bool enabled) {// Отключить все кнопки. В противном случае // 'A' будет нажимать на тот, который находится в фокусе. btnController.IsEnabled =включен; btnStart.IsEnabled =включен; } private async void Gamepad_GamepadRemoved (отправитель объекта, Gamepad e) {_Gamepad =null; await Dispatcher.RunAsync (CoreDispatcherPriority.Normal, () => {tbRead.Text ="Контроллер удален";}); } private async void Gamepad_GamepadAdded (отправитель объекта, Gamepad e) {_Gamepad =e; ждать Dispatcher.RunAsync (CoreDispatcherPriority.Normal, () => {tbRead.Text ="Контроллер добавлен";}); } private async void btnController_Click (отправитель объекта, RoutedEventArgs e) {DisableEnableButtons (false); while (true) {ожидание Task.Delay (TimeSpan.FromMilliseconds (3)); если (_Gamepad ==null) {продолжить; } // Получить текущее состояние var read =_Gamepad.GetCurrentReading (); если (Math.Abs (чтение.LeftThumbstickY) <_ActionPoint) {ArduinoDigitalWrite (_LeftForward, PinState.LOW); ArduinoDigitalWrite (_LeftBackward, PinState.LOW); sldrLeftSpeed.Value =0; } иначе, если (чтение.LeftThumbstickY> =_ActionPoint) {ArduinoDigitalWrite (_LeftForward, PinState.HIGH); ArduinoDigitalWrite (_LeftBackward, PinState.LOW); sldrLeftSpeed.Value =255 * Math.Abs (чтение.LeftThumbstickY) * _SpeedLimit; } иначе, если (чтение.LeftThumbstickY <=-_ActionPoint) {ArduinoDigitalWrite (_LeftForward, PinState.LOW); ArduinoDigitalWrite (_LeftBackward, PinState.HIGH); sldrLeftSpeed.Value =255 * Math.Abs (чтение.LeftThumbstickY) * _SpeedLimit; } если (Math.Abs (read.RightThumbstickY) <_ActionPoint) {ArduinoDigitalWrite (_RightForward, PinState.LOW); ArduinoDigitalWrite (_RightBackward, PinState.LOW); sldrRightSpeed.Value =0; } иначе, если (чтение.RightThumbstickY> =_ActionPoint) {ArduinoDigitalWrite (_RightForward, PinState.HIGH); ArduinoDigitalWrite (_RightBackward, PinState.LOW); sldrRightSpeed.Value =255 * Math.Abs (чтение.RightThumbstickY) * _SpeedLimit; } иначе, если (чтение.RightThumbstickY <=-_ActionPoint) {ArduinoDigitalWrite (_RightForward, PinState.LOW); ArduinoDigitalWrite (_RightBackward, PinState.HIGH); sldrRightSpeed.Value =255 * Math.Abs (чтение.RightThumbstickY) * _SpeedLimit; }}} private void ArduinoDigitalWrite (байтовый порт, состояние PinState) {// игнорировать повторяющиеся команды var exists =_CurrentPinStates.ContainsKey (port); если (! существует || _CurrentPinStates [порт]! =состояние) {_CurrentPinStates [порт] =состояние; _arduino.digitalWrite (порт, состояние); }} private void ArduinoAnalogWrite (порт байта, значение ushort) {// игнорировать повторяющиеся команды var exists =_CurrentSpeedValues.ContainsKey (port); если (! существует || _CurrentSpeedValues [порт]! =значение) {_CurrentSpeedValues [порт] =значение; _arduino.analogWrite (порт, значение); }}}
Производственный процесс
- Система посещаемости с использованием Arduino и RFID с Python
- Универсальный пульт дистанционного управления с использованием Arduino, 1Sheeld и Android
- Вольтметр своими руками с использованием Arduino и смартфона
- Использование Интернета вещей для удаленного управления манипулятором
- Измерение частоты и рабочего цикла с использованием Arduino
- Сонар с использованием Arduino и отображение при обработке IDE
- Управление яркостью светодиода с помощью Bolt и Arduino
- Простая и умная роботизированная рука с использованием Arduino
- Полный контроль над вашим телевизором с помощью Alexa и Arduino IoT Cloud
- FM-радио с использованием Arduino и RDA8057M