工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

FirmataとXbox OneコントローラーでArduinoローバーをシームレス操作

必要なパーツと材料

  • ノートPC(Windows 10、Bluetoothドングル、Visual Studio 2015)
  • フラッシングライト(安全用)
  • パーツ数量備考
    Xbox Oneコントローラー + Windows用ワイヤレスアダプター1PC接続用
    Bluetoothモジュール(HC-05/HC-06またはBlueSMiRF Silver)1ArduinoとPC間通信用
    Arduino UNO1
    ローバーキット(シャーシ、ホイール、DCギアモーター×2、L298Nドライバー、9V電池ボックス等)1
    単3電池ボックス 6本用1モーター用独立電源

    使用ソフトウェア

    プロジェクト概要

    自律動作用キットとして購入したローバーを、Xbox Oneコントローラーで手動操作できるように改造。Firmataプロトコルを使用することで、Arduino側には標準のStandardFirmataスケッチを書き込むだけで済み、制御ロジックはPC側のUWPアプリに集約しています。

    ハードウェア組み立て

    モータードライバー(L298N)接続

    L298Nは2チャネルHブリッジで、各モーターの正転/逆転とPWM速度制御が可能。電源はモーター用(9V)とArduino用を分離し、GNDのみ共通化。

    L298NピンArduinoピン機能
    ENAD10 (PWM)左モーター速度
    IN1D9左モーター方向
    IN2D8左モーター方向
    IN3D7右モーター方向
    IN4D6右モーター方向
    ENBD5 (PWM)右モーター速度

    方向制御:IN1/IN2(またはIN3/IN4)の一方をHIGH、他方をLOWで正転/逆転。両方LOWで停止。PWM値(0-255)で速度制御。

    Bluetooth接続

    HC-06のRX/TXをArduinoのTX/RXにクロス接続、5VとGNDを供給。

    Arduino側:StandardFirmata

    Arduino IDEの例「StandardFirmata」を書き込むだけ。Bluetoothモジュールの品質によりボーレートを9600に下げています(スケッチ内でハードコード変更)。

    動作確認:Windows Remote Arduino Experienceアプリ

    プログラミング不要で動作確認可能。ストアアプリでBluetooth接続後、PWMページでD5/D10に値を設定、DigitalページでD6-D9を操作するとモーターが回転します。

    UWPアプリ:コントローラーとFirmataの仲介役

    XAMLで「Start」「Controller」ボタンとステータステキストを配置。C#コードビハインドで以下を実装:

    1. Bluetooth経由でFirmata接続確立
    2. Xbox Oneコントローラーの左右サムスティックY軸を監視
    3. デッドゾーン(±0.15)を設け、前倒しで前進、後ろ倒しで後進
    4. PWM値 = スティック傾き × 255 × 0.75(速度制限)
    5. 重複コマンド送信防止で通信効率向上

    ソースコード

    XAML(MainPage.xaml)

    <StackPanel Orientation="Vertical">
      <Button Name="btnStart" Click="btnStart_Click" FontSize="50" Width="400" Content="Start" />
      <Button Name="btnController" Content="Controller" FontSize="50" Width="400" IsEnabled="False" Click="btnController_Click" />
      <TextBlock Name="tbRead" FontSize="20" Foreground="Gray" />
    </StackPanel>
    

    C#(MainPage.xaml.cs)

    public sealed partial class MainPage : Page {
      private BluetoothSerial _bluetooth;
      private RemoteDevice _arduino;
      private UwpFirmata _firmata = null;
      private Gamepad _gamepad = null;
      private double _speedLimit = 0.75;
      private double _actionPoint = 0.15;
      
      // ピン定義
      private byte _leftForward = 6, _leftBackward = 7, _leftPwm = 5;
      private byte _rightForward = 9, _rightBackward = 8, _rightPwm = 10;
      
      // 重複送信防止用キャッシュ
      private Dictionary<byte, PinState> _pinStates = new Dictionary<byte, PinState>();
      private Dictionary<byte, ushort> _speedValues = new Dictionary<byte, ushort>();
    
      public MainPage() { this.InitializeComponent(); }
    
      private void btnStart_Click(object sender, RoutedEventArgs e) {
        btnStart.IsEnabled = false;
        Gamepad.GamepadAdded += Gamepad_GamepadAdded;
        Gamepad.GamepadRemoved += Gamepad_GamepadRemoved;
        
        _bluetooth = new BluetoothSerial("HC-06");
        _bluetooth.ConnectionLost += BluetoothConnectionLost;
        _bluetooth.ConnectionFailed += BluetoothConnectionFailed;
        _bluetooth.ConnectionEstablished += OnConnectionEstablished;
        
        _firmata = new UwpFirmata();
        _arduino = new RemoteDevice(_firmata);
        _firmata.begin(_bluetooth);
        _bluetooth.begin(9600, SerialConfig.SERIAL_8N1);
        _arduino.DeviceReady += ArduinoDeviceReady;
      }
    
      private void OnConnectionEstablished() {
        Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
          btnController.IsEnabled = true;
          // 全モーター停止で初期化
          ArduinoDigitalWrite(_leftForward, PinState.LOW);
          ArduinoDigitalWrite(_leftBackward, PinState.LOW);
          ArduinoDigitalWrite(_rightForward, PinState.LOW);
          ArduinoDigitalWrite(_rightBackward, PinState.LOW);
        });
      }
    
      private async void btnController_Click(object sender, RoutedEventArgs e) {
        btnController.IsEnabled = false; btnStart.IsEnabled = false;
        
        while (true) {
          await Task.Delay(TimeSpan.FromMilliseconds(3));
          if (_gamepad == null) continue;
          
          var reading = _gamepad.GetCurrentReading();
          
          // 左モーター制御
          ControlMotor(reading.LeftThumbstickY, _leftForward, _leftBackward, _leftPwm);
          // 右モーター制御
          ControlMotor(reading.RightThumbstickY, _rightForward, _rightBackward, _rightPwm);
        }
      }
    
      private void ControlMotor(double stickY, byte forwardPin, byte backwardPin, byte pwmPin) {
        if (Math.Abs(stickY) < _actionPoint) {
          ArduinoDigitalWrite(forwardPin, PinState.LOW);
          ArduinoDigitalWrite(backwardPin, PinState.LOW);
          ArduinoAnalogWrite(pwmPin, 0);
        } else if (stickY >= _actionPoint) { // 前進
          ArduinoDigitalWrite(forwardPin, PinState.HIGH);
          ArduinoDigitalWrite(backwardPin, PinState.LOW);
          ArduinoAnalogWrite(pwmPin, (ushort)(255 * Math.Abs(stickY) * _speedLimit));
        } else { // 後進
          ArduinoDigitalWrite(forwardPin, PinState.LOW);
          ArduinoDigitalWrite(backwardPin, PinState.HIGH);
          ArduinoAnalogWrite(pwmPin, (ushort)(255 * Math.Abs(stickY) * _speedLimit));
        }
      }
    
      private void ArduinoDigitalWrite(byte port, PinState state) {
        if (!_pinStates.ContainsKey(port) || _pinStates[port] != state) {
          _pinStates[port] = state;
          _arduino.digitalWrite(port, state);
        }
      }
    
      private void ArduinoAnalogWrite(byte port, ushort value) {
        if (!_speedValues.ContainsKey(port) || _speedValues[port] != value) {
          _speedValues[port] = value;
          _arduino.analogWrite(port, value);
        }
      }
      // ... イベントハンドラ類省略 ...
    }
    

    ポイント

    製造プロセス

    1. Python連携で信頼性向上: Arduino RFID勤怠管理システム
    2. Arduinoと1Sheeldで作る万能Androidリモコン──IR制御で家電を一括操作
    3. Arduinoとスマホで作るスマート電圧計 – 簡単DIYプロジェクト
    4. IoTで遠隔操作する自作ロボットアーム:Arduino MKR1000とSimulink、ThingSpeak活用
    5. Arduino UNOで周波数とデューティサイクルを高精度測定
    6. Arduino超音波センサーとProcessingで作るリアルタイム距離測定ソナー
    7. Bolt IoTとArduino UNOでLED輝度をシームレス制御
    8. スマートなArduino制御ロボットアームの製作:簡単DIYチュートリアル
    9. Arduino IoT CloudとAlexaでテレビを音声操作:ステップバイステップガイド
    10. Arduino NanoとRDA5807Mで作るコンパクトFMラジオ
    11. スマホで家庭照明をシームレス制御 - 1Sheeld活用