Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Bestuur een Arduino-rover naadloos met Firmata en een Xbox One-controller

Onderdelen en benodigdheden

Microsoft Xbox One-controller + Wireless Adapter voor Windows 1
Bluetooth-module (HC-05, HC-06 of BlueSMiRF Silver) 1
Arduino UNO 1
Rover-kit (chassis, 2 wielen, 2 DC-gearmotoren, L298N motor-driver, 9V-batterijhouder, sensor shield) 1
Extra batterijhouder 6xAA (voor motoren) 1
Laptop met Windows 10 (Bluetooth-dongle, Visual Studio 2015+) 1

Apps en online diensten

  • Microsoft Windows 10 IoT Core – UWP-app als tussenstuk tussen Firmata en Xbox-controller

Over dit project

Ik kocht een goedkope rover-kit (bedoeld voor autonoom rijden met ultrasoon/servo). Maar ik wilde het handmatig besturen met een Xbox One-controller via het Firmata-protocol. En het werkt uitstekend!

Kit bouwen

De handleiding was in het Chinees, maar logisch opgebouwd. Eén basisplaat: componenten zowel boven als onder. Twee batterijhouders: één voor Arduino, één voor motoren (apart nodig, anders lopen motoren niet).

Motor-aansluiting – L298N pinlayout

De L298N dual H-brug stuurt snelheid en richting van beide motoren via signalen van de Arduino.

  • Motor 1: + / –
  • Power IN: 9V (losse batterijhouder)
  • Gemeenschappelijke GND (Arduino + motor-batterij)
  • ENA → Arduino D10 (PWM, wit)
  • IN1 → D9 (grijs), IN2 → D8 (paars)
  • IN3 → D7 (blauw), IN4 → D6 (groen)
  • ENB → D5 (PWM, geel)
  • Motor 2: + / –
  • Jumper bij 12V-invoer niet verwijderen (we blijven onder 12V)

Belangrijk: Arduino en motor-driver hebben elk hun eigen voeding, maar GND moet gemeenschappelijk zijn.

Arduino-pinlayout

D5–D10 aangesloten op ENA, IN1–IN4, ENB. D5 en D10 zijn PWM-pins (getild ~) voor snelheidsregeling. D6–D9 zijn gewone GPIO voor richting:

  • Beide LOW → motor stil
  • Eén HIGH, één LOW → één richting
  • Omgekeerd → andere richting

Zonder PWM-signaal (D5/D10) beweegt niets!

Bluetooth-aansluiting

HC-06: RX↔TX (kruisen), 5V en GND van Arduino.

Firmata-sketch op Arduino

Gewoon StandardFirmata uit de Arduino IDE-voorbeelden uploaden (TX/RX loskoppelen voor upload). Let op: mijn Bluetooth-module was slecht, dus baudrate in de sketch verlaagd naar 9600.

Testen zonder programmeren

Gebruik de Windows Remote Arduino Experience-app (Store, werkt ook op Windows 10 Mobile):

  1. Koppelen met HC-06
  2. PWM-pagina: pin 5 inschakelen, waarde 128
  3. Digital-pagina: pin 6 HIGH zetten → motor draait!
  4. Richting wisselen: pin 6 LOW, pin 7 HIGH
  5. Zelfde voor pin 10 (PWM) + pin 8/9 (richting motor 2)

De UWP-app als schakel

Een UWP-app (C#/XAML) luistert naar de Xbox-controller en vertaalt thumbstick-waarden naar Firmata-commando's.

Principes:

  • Linker thumbstick Y-as → linker motor (vooruit/achteruit)
  • Rechter thumbstick Y-as → rechter motor
  • Dode zone (_ActionPoint = 0.15) → motor stil
  • PWM-waarde = 255 × |thumbstick| × _SpeedLimit (0,75)
  • Firmata: PWM = analogWrite op digitale pin
  • Duplicate-commando's filteren (performance)

Let op: Bij lage PWM-waarden "wierpen" motoren (normaal). Daarom twee voedingen!

Code

XAML-besturingselementen

<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>

Code-behind (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, _LeftValue = 5;
  private byte _RightForward = 9, _RightBackward = 8, _RightValue = 10;
  private Dictionary<byte, PinState> _CurrentPinStates = new Dictionary<byte, PinState>();
  private Dictionary<byte, ushort> _CurrentSpeedValues = 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 async void OnConnectionEstablished() {
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
      DisableEnableButtons(true);
      ArduinoDigitalWrite(_LeftForward, PinState.LOW);
      ArduinoDigitalWrite(_LeftBackward, PinState.LOW);
      ArduinoDigitalWrite(_RightBackward, PinState.LOW);
      ArduinoDigitalWrite(_RightForward, PinState.LOW);
    });
  }

  private async void btnController_Click(object sender, RoutedEventArgs e) {
    DisableEnableButtons(false);
    while (true) {
      await Task.Delay(TimeSpan.FromMilliseconds(3));
      if (_Gamepad == null) continue;
      var reading = _Gamepad.GetCurrentReading();

      // Linker motor
      if (Math.Abs(reading.LeftThumbstickY) < _ActionPoint) {
        ArduinoDigitalWrite(_LeftForward, PinState.LOW);
        ArduinoDigitalWrite(_LeftBackward, PinState.LOW);
      } else if (reading.LeftThumbstickY >= _ActionPoint) {
        ArduinoDigitalWrite(_LeftForward, PinState.HIGH);
        ArduinoDigitalWrite(_LeftBackward, PinState.LOW);
        ArduinoAnalogWrite(_LeftValue, (ushort)(255 * Math.Abs(reading.LeftThumbstickY) * _SpeedLimit));
      } else {
        ArduinoDigitalWrite(_LeftForward, PinState.LOW);
        ArduinoDigitalWrite(_LeftBackward, PinState.HIGH);
        ArduinoAnalogWrite(_LeftValue, (ushort)(255 * Math.Abs(reading.LeftThumbstickY) * _SpeedLimit));
      }

      // Rechter motor (analog)
      if (Math.Abs(reading.RightThumbstickY) < _ActionPoint) {
        ArduinoDigitalWrite(_RightForward, PinState.LOW);
        ArduinoDigitalWrite(_RightBackward, PinState.LOW);
      } else if (reading.RightThumbstickY >= _ActionPoint) {
        ArduinoDigitalWrite(_RightForward, PinState.HIGH);
        ArduinoDigitalWrite(_RightBackward, PinState.LOW);
        ArduinoAnalogWrite(_RightValue, (ushort)(255 * Math.Abs(reading.RightThumbstickY) * _SpeedLimit));
      } else {
        ArduinoDigitalWrite(_RightForward, PinState.LOW);
        ArduinoDigitalWrite(_RightBackward, PinState.HIGH);
        ArduinoAnalogWrite(_RightValue, (ushort)(255 * Math.Abs(reading.RightThumbstickY) * _SpeedLimit));
      }
    }
  }

  private void ArduinoDigitalWrite(byte port, PinState state) {
    if (!_CurrentPinStates.ContainsKey(port) || _CurrentPinStates[port] != state) {
      _CurrentPinStates[port] = state;
      _arduino.digitalWrite(port, state);
    }
  }
  private void ArduinoAnalogWrite(byte port, ushort value) {
    if (!_CurrentSpeedValues.ContainsKey(port) || _CurrentSpeedValues[port] != value) {
      _CurrentSpeedValues[port] = value;
      _arduino.analogWrite(port, value);
    }
  }
  // ... event handlers voor Bluetooth/Gamepad (zie origineel)
}

Productieproces

  1. Betrouwbaar Arduino RFID Aanwezigheidssysteem Aangedreven door Python
  2. Universele Android-afstandsbediening bouwen met Arduino, 1Sheeld en IR-besturing
  3. Een slimme voltmeter bouwen met Arduino en smartphone – Eenvoudig DIY-project
  4. Externe IoT-besturing van een zelfgebouwde robotarm
  5. Nauwkeurige Frequentie- en Duty Cycle-meting met Arduino UNO
  6. Realtime afstandsmeting met Arduino Sonar & Processing visualisatie
  7. Naadloze LED-dimmer met Bolt IoT en Arduino UNO
  8. Bouw een Slimme Arduino-gestuurde Robotarm: Eenvoudige DIY Handleiding
  9. Je TV bedienen met Alexa via Arduino IoT Cloud – stapsgewijze handleiding
  10. Bouw een compacte FM-radio met Arduino Nano en RDA5807M
  11. Naadloze Smartphone-besturing van Huisverlichting met 1Sheeld