Arduino + Einheit. Radio-FPV-Auto auf dem Gamepad / Sudo Null IT News

Hallo. Ich erzähle Ihnen, wie ich ein Auto auf einem Arduino-Controller gebaut habe und Unity Signale von einem Gamepad empfangen, das Auto über einen Funkkanal gesteuert, eine Benutzeroberfläche und ein Bild einer FPV-Kamera angezeigt hat.

Warum

Ziel Projekt Es war
• Probieren Sie eine Reihe von Arduino und Unity aus
• Steuern Sie das Auto mit einem weitreichenden Funksignal anstelle von Wi-Fi
• Videobild aufnehmen
• Steuerung über Gamepad
• Alles über ein Unity-Fenster

Warum

Auf dem Kanal Guyver Ich habe mich mit der Ausstattung von Koptern und mit Arduino-Controllern vertraut gemacht. Das Interesse verschwand schließlich aufgrund des Interesses an der Spiele-Engine und der Branche als Ganzes. Was könnte noch passieren, wenn nicht der Versuch, die zuvor gesammelten Erfahrungen zu kombinieren.

Arbeitsalgorithmus

  1. Die Spiel-Engine empfängt ein Signal vom Gamepad

  2. Konvertiert Vector2 in die Befehlszeile und sendet an USB-verbundenes Arduino

  3. Arduino hat ein Sendermodul, das einen Befehl über die Luft sendet

  4. Die Onboard-Arduina mit dem Empfängermodul empfängt ein Funksignal, wandelt es um, um die Motorräder und Servos mit Spannung zu versorgen

  5. FPV-Kamera an Bord, überträgt analoges Videosignal, arbeitet unabhängig vom Rest des Systems

  6. Der Videoempfänger wird an den PC angeschlossen, digitalisiert das Video und überträgt es an Unity

  7. Was die Kamera sieht, wird auf dem Bildschirm angezeigt

  8. Die Benutzeroberfläche wird auf dem Bildschirm eingeblendet

Mehr

Die Unity-Input-Klasse funktioniert problemlos mit einem Gamepad. Die Joystick-Position ist ein Vector2-Wert, der drahtlos übertragen werden muss. Ich habe den zweiten Joystick nur für eine Achse verwendet – die Drehachse der Kamera an Bord der Maschine links und rechts.

IEnumerator update() { while(true) {float[] Achsen = {Input.GetAxis(“Horizontal”), Input.GetAxis(“Vertical”), Input.GetAxis(“Stick Y”), Input.GetAxis(“Stick X”) }; Byte[] Signale = neues Byte[4]; Signal = “”; for (int i = 0; i Um das Funksignal vom Computer zum Onboard-Arduino zu übertragen, habe ich ein weiteres Board verwendet, das ich über den USB-Port mit dem Laptop verbunden habe.

Wussten Sie übrigens, dass es eingebaute Funkmodule direkt in das Arduino-Board gibt? Ich nicht. Ich habe ein Arduino-Board verwendet Uno und Funkmodul nrf24l01

Für diesen Teil des Algorithmus habe ich zwei Skripte verwendet. Einer von der Unity-Seite, der mit Arduino arbeitet, wandelt das Spiel Vector2 und andere Signale in eine Zeichenfolge um, die für die Übertragung über einen Funkkanal geeignet ist. Einen Vermögenswert verwendet Ardity.

256 Bytes zu verwalten, Carl! Jede Joystickachse belegt bei Funkübertragung 1 Byte, übrig bleiben 253! Wofür kann man den Rest noch verwenden? Zum Beispiel für boolesche Befehle: Scheinwerfer einschalten, Blinker, Kolben und Servos einschalten, eine Luke öffnen oder einen Kran hochfahren …

Der zweite von der Arduino-Seite zur Signalübertragung.

Arduino-Sendercode #include #include #include RF24-Radio (9, 10); Byte-Adresse[][6] = {“1Knoten”, “2Knoten”, “3Knoten”, “4Knoten”, “5Knoten”, “6Knoten”}; //mögliche Pipe-Nummern-Byte-Werte[4] = {0,0,0,0}; void setup () {Serial.begin (9600); Serial setTimeout (10); txsetup(); Serial.println (“Arduino lebt!!”); Verzögerung (100); } void loop() { while (Serial.available()) {String input = Serial.readStringUntil(“;”); setArray (Eingabe); radio.write(&values, sizeof(values)); } } void SetArray(String input) { input += “.”; if (!isDigit(input[0])) Rückkehr; int intIndex = 0; Stringbuf = “”; for(int i = 0; i < input.length(); i++) { if (isDigit(input[i])) { buf += Eingabe[i]; } Else {Werte[intIndex] = buf.toInt(); buf = ""; intIndex++; } } } void txSetup () { radio.begin (); // Modul aktivieren //radio.setAutoAck(1); // Bestätigungsmodus, 1 an 0 aus //radio.setRetries (0, 15); // (Zeit zwischen Versuchen zu erreichen, Anzahl der Versuche) //radio.enableAckPayload(); // erlauben, dass Daten als Antwort auf ein eingehendes Signal gesendet werden radio.setPayloadSize(4); // Paketgröße, in Byte // 32 radio.openWritingPipe(address[5]); // Wir sind Pipe 0, öffnen einen Datenkanal radio.setChannel (0x79); // Kanal auswählen (kein Rauschen!) radio.setPALevel (RF24_PA_LOW); // Sendeleistungspegel. Optional RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX radio.setDataRate (RF24_250KBPS); // Tauschrate. Optional RF24_2MBPS, RF24_1MBPS, RF24_250KBPS //sollten bei Empfänger und Sender gleich sein! //bei der niedrigsten Geschwindigkeit haben wir die höchste Empfindlichkeit und Reichweite!! radio.powerUp(); // starte radio.stopListening(); // kein Radio hören, wir sind ein Sender }

Um das Funksignal zu empfangen und umzuwandeln, habe ich eine Skizze für das zweite Arduino geschrieben. Die Räder funktionieren nach dem Schema des Panzers – zwei führende Räder mit einem Geschwindigkeitsunterschied erzeugen eine Kurve (oder eine Kurve auf der Stelle). Arduino sendet Signale an den MRL298-Treiber und verteilt bereits Spannung an die Motoren.

#include #include #include #include #define motor1in 2 #define motor1pwm 5 #define motor2in 4 #define motor2pwm 6 #define fpvYpin 3 RF24 radio (9, 10); Byte-Adresse[][6] = {“1Knoten”, “2Knoten”, “3Knoten”, “4Knoten”, “5Knoten”, “6Knoten”}; //mögliche Pipe-Nummern-Byte-Werte[4] = {0, 0, 0, 0}; Servo fpvY; void setup () { fpvY.attach (fpvYpin); Serial.begin (9600); Serial setTimeout (10); motorSetup(); rxsetup(); Verzögerung (100); } void loop() {if (radio.available()) {while (radio.available()) {radio.read(&values, sizeof(values)); setMotors(map(values[0]0, 255, -255, 255), map(values[1], 0, 255, -255, 255)); fpvY.write(map(Werte[3], 0, 255, 45, 135)); } } } void setMotors (int inx, int iny) // -255 bis 255 { setMotor (iny + inx, motor1pwm, motor1in); setMotor (iny – inx, motor2pwm, motor2in); } void setMotor (int mspeed, int pinPwm, int pinIn) {if (mspeed > 0) // forward {analogWrite (pinPwm, mspeed); DigitalWrite (PinIn, 0); } else if (mspeed <0) // zurück {analogWrite (pinPwm, 255 + mspeed); DigitalWrite (PinIn, 1); } Else // Bremse { DigitalWrite (pinPwm, 0); DigitalWrite (PinIn, 0); aufrechtzuerhalten. aufrechtzuerhalten. Void MotorSetup () { PinMode (Motor1in, AUSGANG); PinMode (Motor2in, AUSGANG); PinMode (Motor1pwm, AUSGANG); PinMode (motor2pwm, AUSGANG); aufrechtzuerhalten. void rxSetup () {radio.begin (); // Modul aktivieren //radio.setAutoAck(1); // Bestätigungsmodus, 1 an 0 aus //radio.setRetries (0, 15); // (Zeit zwischen Versuchen zu erreichen, Anzahl der Versuche) //radio.enableAckPayload(); // erlauben, dass Daten als Antwort auf ein eingehendes Signal gesendet werden radio.setPayloadSize(4); // Paketgröße, in Byte // 32 radio.openReadingPipe(1, Adresse[5]); // möchte Pipe 0 hören radio.setChannel (0x79); // Kanal auswählen (kein Rauschen!) radio.setPALevel (RF24_PA_LOW); // Sendeleistungspegel. Optional RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX radio.setDataRate (RF24_250KBPS); // Tauschrate. Optional RF24_2MBPS, RF24_1MBPS, RF24_250KBPS //sollten bei Empfänger und Sender gleich sein! //bei der niedrigsten Geschwindigkeit haben wir die höchste Empfindlichkeit und Reichweite!! radio.powerUp(); // starte radio.startListening(); // Starte die Übertragung, wir sind das Empfangsmodul }

Hinweis Bene: Controller by Ursprünglich konfiguriert, um Signale nicht länger als 1 Sekunde zu empfangen, was für eine ununterbrochene Steuerung von der Steuerung nicht akzeptabel ist.

Zur Übertragung des Videosignals habe ich die 3in1-Kamera (Kamera, Sender, Antenne) von Eachine an Bord des Autos verwendet, die unabhängig vom restlichen System des Autos arbeitet, ein Eigenleben führt.

Um das Videosignal zu empfangen, habe ich einen separaten Empfänger verwendet, der über USB mit dem Laptop verbunden ist. Der EasyCAP-Empfänger wandelt den analogen Videostream in einen digitalen um und wird vom Laptop als Webcam erkannt, und die Game-Engine bietet Lösungen für die Arbeit mit solchen Geräten.

Code für Videostream mit System.Linq; mit UnityEngine; mit UnityEngine.UI;

[RequireComponent(typeof(RawImage))]
öffentliche Klasse WebTexture : MonoBehavior { RawImage _raw; WebCamTexture _texture; private void Start() { foreach (var c in WebCamTexture.devices) Debug.Log(c.name); if (WebCamTexture.devices.Length > 0) SetTexture(WebCamTexture.devices[0]); } public void _SwitchWebCam() { var devicesEnumerator = WebCamTexture.devices.Where(x => new WebCamTexture(x.name) != null); // TODO Wie überprüfe ich die nicht virtuelle Kamera? var devices = devicesEnumerator.ToArray(); if (devices.Length > 1) {int usedDeviceIndex = 0; for (int i = 0; i < devices.Length; i++) if (devices[i].name == _texture.deviceName) usedDeviceIndex = i; int newDeviceIndex = usedDeviceIndex == (devices.Length - 1) ? 0 : usedDeviceIndex + 1; SetTexture(Geräte[newDeviceIndex]); } } private void SetTexture (WebCamDevice-Gerät) { if (_texture != null && _texture.isPlaying) _texture.Stop(); _texture = new WebCamTexture(device.name); _texture.requestedFPS = 30; _raw = GetComponent(); _raw.texture = _texture; _texture.Play(); } }

Insgesamt erhalten wir ein Rohprodukt mit großem Potenzial.

Dies ist mein erster Beitrag. Mal sehen was passiert. Das Projekt läuft GitHub im freien Zugang. Download nicht vergessen Anlage mit der seriellen Schnittstelle zu arbeiten.

Ich bestreite nicht, dass es wahrscheinlich prägnantere Lösungen gibt, um sich mit einem Computer mit einem Funkgerät anzufreunden, während nicht zwei USB-Anschlüsse gleichzeitig verwendet werden, ist dies sehr umständlich. Ich biete meine Lösung an. Irgendwelche Ideen? Schreiben Sie, was Sie darüber denken.

Similar Posts

Leave a Reply

Your email address will not be published.