-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Workshop-Day: Play from MicroProcesseur with Bluetooth #292
Comments
Compressed with bit shift |
Suite à cet exercice, pour plus de facilité qu'avec des nombres, je vous ai ajouté des lettres. Il y a aussi, basé sur la grammaire de Bluetooth Electronics :
N'oubliez pas le retour de ligne if(text=="G") pressA(true);
else if(text=="BEDEBUG") m_useBluetoothElectronicFeedBack=true;
else if(text=="bedebug") m_useBluetoothElectronicFeedBack=false;
else if(text=="PINSWITCH") SwitchAllPins();
else if(text=="g") pressA(false);
else if(text=="Y") pressY(true);
else if(text=="y") pressY(false);
else if(text=="B") pressX(true);
else if(text=="b") pressX(false);
else if(text=="R") pressB(true);
else if(text=="r") pressB(false);
else if(text=="S" || text=="START") pressMenuRight(true);
else if(text=="s" || text=="start") pressMenuRight(false);
else if(text=="BACK") pressMenuLeft(true);
else if(text=="back") pressMenuLeft(false);
else if(text=="H") pressHomeXboxButton(true);
else if(text=="h") pressHomeXboxButton(false);
else if(text=="M") pressMenuLeft(true);
else if(text=="m") pressMenuLeft(false);
else if(text=="N") pressMenuRight(true);
else if(text=="n") pressMenuRight(false);
else if(text=="BA" || text=="BD") pressA(true);
else if(text=="ba"|| text=="bd") pressA(false);
else if(text=="BY"|| text=="BU") pressY(true);
else if(text=="by"|| text=="bu") pressY(false);
else if(text=="BX"|| text=="BL") pressX(true);
else if(text=="bx"|| text=="bl") pressX(false);
else if(text=="BB"|| text=="BR") pressB(true);
else if(text=="bb"|| text=="br") pressB(false);
else if(text=="AU") pressArrowN();
else if(text=="AC") releaseDPad();
else if(text=="AR") pressArrowE();
else if(text=="AD") pressArrowS();
else if(text=="AL") pressArrowW();
else if(text=="AN") pressArrowN();
else if(text=="AE") pressArrowE();
else if(text=="AS") pressArrowS();
else if(text=="AW") pressArrowW();
else if(text=="ANW") pressArrowNW();
else if(text=="ANE") pressArrowNE();
else if(text=="ASE") pressArrowSE();
else if(text=="ASW") pressArrowSW();
else if(text=="ANW") pressArrowNW();
else if(text=="ANE") pressArrowNE();
else if(text=="ASE") pressArrowSE();
else if(text=="ASW") pressArrowSW();
else if(text=="RECORD") recordStart();
else if(text=="record") recordStop();
else if(text=="SBL") pressLeftSideButton(true);
else if(text=="sbl") pressLeftSideButton(false);
else if(text=="SBR") pressRightSideButton(true);
else if(text=="sbr") pressRightSideButton(false);
else if(text=="JL") pressLeftStick(true);
else if(text=="jl") pressLeftStick(false);
else if(text=="TL") setTriggerLeftPercent(1);
else if(text=="tl") setTriggerLeftPercent(0);
else if(text=="TR") setTriggerRightPercent(1);
else if(text=="tr") setTriggerRightPercent(0);
else if(text=="JR") pressRightStick(true);
else if(text=="jr") pressRightStick(false);
else if(text=="MR") pressMenuRight(true);
else if(text=="mr") pressMenuRight(false);
else if(text=="ML") pressMenuLeft(true);
else if(text=="ml") pressMenuLeft(false);
else if(text=="MC") pressHomeXboxButton(true);
else if(text=="mc") pressHomeXboxButton(false);
// Big Grey Circle
else if(text=="M"){}
// Big Rectancle
else if(text=="W"){}
// Switch vertical on off
else if(text=="C") m_useHardwareJoystick=true;
else if(text=="c") m_useHardwareJoystick=false;
// Power Button Switch on off
else if(text=="D") digitalWrite(m_lepPin, HIGH);
else if(text=="d") digitalWrite(m_lepPin, LOW);
else if(text=="V") setVibrationOn(true);
else if(text=="v") setVibrationOn(false);
|
Ce qu'il faut savoir sur la communication entre un module HC-05 et Unity3D, c'est que cela peut être complexe. Les codes varient d'une plateforme à l'autre. Si vous devez réaliser cette intégration, il est recommandé d'acheter un ou deux plug-ins directement depuis l'Asset Store, puis d'apprendre à les utiliser : Si vous ne souhaitez pas acheter de plug-in, vous pouvez tenter de coder votre propre solution. Cependant, il est important de noter que maintenir un tel code compatible au fil des années peut être particulièrement difficile. Une alternative qui peut fonctionner dans des conditions spécifiques consiste à exécuter un serveur sur le PC connecté à l'appareil Bluetooth, puis à établir une communication via ce serveur. Pourquoi ? Parce que Python est puissant, flexible et bénéficie d'un excellent support communautaire. Vous pouvez trouver ici quelques scripts Python pour configurer une redirection Port Série N'hésitez pas si vous avez besoin d'autres ajustements ou d'informations complémentaires !
import socket
import serial
import serial.tools.list_ports
import struct
import threading
import time
# Configuration
UDP_TO_SERIAL_PORT = 7046 # UDP port for receiving data to send to the serial port
SERIAL_TO_UDP_PORT = 7045 # UDP port for sending data received from the serial port
UDP_TARGET_IP = "127.0.0.1" # Target IP for UDP communication
SERIAL_BAUDRATE = 9600
DEVICE_ID = "98D331F71DA0"
# Functions for serial communication
def list_serial_ports():
ports = serial.tools.list_ports.comports()
for port in ports:
print(f"Device: {port.device}")
print(f"Name: {port.name}")
print(f"Description: {port.description}")
print(f"HWID: {port.hwid}")
print(f"VID: {port.vid}")
print(f"PID: {port.pid}")
print(f"Serial Number: {port.serial_number}")
print(f"Location: {port.location}")
print(f"Manufacturer: {port.manufacturer}")
print(f"Product: {port.product}")
print(f"Interface: {port.interface}")
print("-" * 40)
def find_device_com(device_id):
ports = serial.tools.list_ports.comports()
for port in ports:
if port.serial_number == device_id:
return port.device
if device_id in port.hwid:
return port.device
return None
# Thread for UDP -> Serial
def udp_to_serial(udp_port, serial_port):
udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_sock.bind(("0.0.0.0", udp_port))
print(f"Listening for UDP data on port {udp_port}...")
while True:
data, addr = udp_sock.recvfrom(1024)
print(f"Received from UDP {addr}: {data}")
serial_port.write(data)
# Thread for Serial -> UDP
def serial_to_udp(serial_port, udp_ip, udp_port):
udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print(f"Sending serial data to {udp_ip}:{udp_port}...")
while True:
if serial_port.in_waiting > 0:
data = serial_port.read(serial_port.in_waiting)
print(f"Received from Serial: {data}")
udp_sock.sendto(data, (udp_ip, udp_port))
time.sleep(0.01)
# Main
if __name__ == "__main__":
# List serial ports
list_serial_ports()
# Find serial device
com_port = find_device_com(DEVICE_ID)
if not com_port:
print(f"Device with ID {DEVICE_ID} not found!")
exit(1)
print(f"Connecting to {com_port}...")
serial_port = serial.Serial(com_port, SERIAL_BAUDRATE, timeout=1)
# Start threads
udp_thread = threading.Thread(target=udp_to_serial, args=(UDP_TO_SERIAL_PORT, serial_port), daemon=True)
serial_thread = threading.Thread(target=serial_to_udp, args=(serial_port, UDP_TARGET_IP, SERIAL_TO_UDP_PORT), daemon=True)
udp_thread.start()
serial_thread.start()
# Keep the main thread alive
try:
print("Press 'E' to exit...")
while True:
time.sleep(1)
if input().strip().upper() == 'E':
print("Exiting...")
break
except KeyboardInterrupt:
print("Shutting down...")
serial_port.close() |
pip install pyserial |
import socket
import threading
# Define the UDP IP address and ports
UDP_IP = "127.0.0.1"
SEND_PORT = 7046
RECEIVE_PORT = 7045
# Create a UDP socket for sending
send_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Create a UDP socket for receiving
receive_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
receive_socket.bind((UDP_IP, RECEIVE_PORT))
# Function to send a message
def send_message(message):
message+="\n"
send_socket.sendto(message.encode(), (UDP_IP, SEND_PORT))
print(f"Sent message: {message}")
# Function to receive a message
def receive_message():
while True:
data, addr = receive_socket.recvfrom(1024) # buffer size is 1024 bytes
print(f"Received message: {data.decode()} from {addr}")
# Example usage
if __name__ == "__main__":
# Start the receiver in a new thread
receiver_thread = threading.Thread(target=receive_message)
receiver_thread.daemon = True
receiver_thread.start()
# Send a message
send_message("Hello, UDP!")
# Keep the main thread alive to allow the receiver thread to run
while True:
user_input = input("Enter message to send: ")
send_message(user_input)
pass |
Dans l'atelier précédent, nous avons vu comment :
Dans cet atelier, nous allons apprendre à utiliser le Bluetooth et les modules HC06/HC05 pour injecter des commandes sur un PC, et donc dans un jeu.
Code
Via Leonardo pour le XInput
Arduino dispose d’une bibliothèque permettant de transformer un Arduino Micro ou un Arduino Leonardo en manette Xbox 360.
Vous pouvez trouver le code ici :
Pour cet atelier, j’ai acheté 4 Leonardo. Je fournirai une adresse MAC HC06 à chaque équipe.
À vous de décider : coopérez ou affrontez-vous dans des jeux à 4 joueurs !
Voir comment configurer un Arduino Leonardo en manette Xbox XInput :
Via ESP32 pour le BLE
J’ai remarqué que beaucoup d’entre vous jouent à des jeux répétitifs en classe 😋.
Aucune critique ici ! Explorons comment utiliser un ESP32 pour automatiser certaines tâches ennuyeuses pour vous.
Le code est disponible ici :
Via Raspberry Pi Pico W
Si vous voulez jouer à Warcraft, vous pourriez risquer d’installer des logiciels sur votre PC.
Mais une alternative consiste à utiliser un Raspberry Pi Pico W pour simuler un clavier et une souris.
Au lieu d'utiliser Scratch To Warcraft Python code comme dans l’atelier précédent, essayons cette fois-ci de simuler directement un clavier et une souris.
Le code se trouve ici :
Wi-Fi et Python
Notez que, si le matériel permet une injection sans installation, vous pouvez également simuler tous les inputs d’un PC en utilisant Python ou C# dans Unity, si vous avez la main sur le PC.
Voici quelques exemples :
Dans cet atelier, nous allons jouer à TowerFall via un ESP32 dans le but de pratiquer l'utilisation du HC05.
https://store.steampowered.com/app/251470/TowerFall_Ascension/
https://youtu.be/iotmElvdsKU?t=1
Les HC05 et HC06 sont des petits composants de communication.
En résumé, ils permettent d’envoyer des caractères UTF8 entre deux appareils.
Si vous vous débrouillez bien avec ça, vous pouvez donc interagir entre des logiciels et de l’électronique via le Bluetooth.
Il y a aussi les TTL, qui permettent cela via USB, mais nous n’en utiliserons pas ici car c’est spécifique à des cas plus limités que le HC05.
Dans notre cas, nous allons pratiquer sur un ESP32 :
Pour communiquer entre le HC05 et l'ESP, nous allons utiliser 4 câbles.
Les deux autres câbles du HC05 servent à changer le nom, le mot de passe et le baudrate.
Dans un code Arduino, nous pouvons lire et envoyé des messages sur le Serial Port ainsi:
En Circuit Python, cela ressebmle au code suivant:
Nous n'allons pas coder ces parties-là. Notre but est de pratiquer l'utilisation du HC05.
Si vous souhaitez voir à quoi peut ressembler le code sur Arduino :
Si vous désirez faire de même en Circuit Python :
L'important est de trouver un moyen de communication qui soit le plus court possible, car la transmission d'informations via Bluetooth est très lente (comparée à la vitesse électrique dans un circuit électrique).
Nous allons donc utiliser des drapeaux ^^
👉 [Vidéo YouTube : Stratégies Bluetooth avec des drapeaux](https://www.youtube.com/watch?v=XKWrbB5th60)
Les drapeaux 🚩
Ce que nous venons de créer, c'est un index. Une table d'index.
Vous en connaissez sûrement une que vous utilisez souvent sur votre téléphone :
👉 [Table d'index des emojis 🍃🍂🍁](https://emojipedia.org/four-leaf-clover)
En informatique, les tables d'index sont partout, y compris dans ce texte que vous lisez actuellement :
👉 [Unicode et UTF-8](https://devblogs.microsoft.com/commandline/windows-command-line-unicode-and-utf-8-output-text-buffer)
Les bases : comment ça fonctionne ?
Face à la diversité des alphabets sur Terre, les Américains ont rapidement compris qu'ils n'étaient pas seuls. Ainsi, nous avons créé des tables pour les Européens avec 2 octets.
Mais avec 20+ langues européennes (et des langues mortes), il a fallu passer à 3 octets. Puis, en intégrant les langues asiatiques, nous sommes allés jusqu'à 4 octets, offrant ainsi 4 milliards de symboles.
👉 C'est ce qu'on appelle l'Unicode 🧙♂️.
Optimisation : exemples d'utilisation
Si votre projet est petit et ne nécessite que 50 actions, vous pouvez utiliser des lettres et des chiffres :
Cela offre 50 à 80 possibilités.
En ajoutant une deuxième lettre, vous obtenez un système un peu plus complexe, mais avec 2500 à 6400 possibilités, suffisant pour de nombreux projets.
Exemple : Piano
Pour les touches, cela suffit, mais pas pour les vélocités. Les développeurs compressent alors l'information sur 3 octets :
👉 [Exemple compressé de données MIDI](#7)
Pour les manettes, un format similaire est utilisé. Par exemple :
Cela peut aussi fonctionner pour les boutons :
👉 [Format compressé pour manettes](#298)
Bluetooth Electronics
Matériel requis :
👉 [Code source](https://github.com/EloiStree/2024_11_21_ESP32HC05RC/blob/main/XESP32HC05RC/XESP32HC05RC.ino)
Applications utiles :
Android : [Téléchargez Bluetooth Electronics](https://play.google.com/store/apps/details?id=com.keuwl.arduinobluetooth&hl=en)
Windows : Utilisez un logiciel de port série.
👉 [Exemple : Serial Port](Software: Serial Debug Assitant #299)
Étapes de configuration
Branchez le HC05 aux pins de votre microcontrôleur (Arduino, Pico W, ESP32, etc.).
Alimentation : Lorsque le HC05 est alimenté, il clignote rouge (mode "découvrable").
Pairage : Depuis Android ou Windows, trouvez l'appareil (ID commençant par
98:D3...
) et entrez le code 1234.Connexion : Sélectionnez le HC05 dans votre application et connectez-vous.
Félicitations ! 🧙♂️
Vous avez établi votre première connexion entre un téléphone et un composant électronique ⚡🔌 !
N'est-ce pas magnifique ? 😋
Maintenant que nous l'avons connecté, essayons de lui faire effectuer une action. Voici deux exemples de tableaux.
Pour des gamepads génériques :
Pour la Xbox :
Comme nous voulons simuler des touches de clavier, des manettes et des activations de pins,
je vous propose d'utiliser 4 caractères avec un retour à la ligne
\n
.Vous retrouverez la convention sur :
[github.com/EloiStree/2024_08_29_ScratchToWarcraft](https://github.com/EloiStree/2024_08_29_ScratchToWarcraft?tab=readme-ov-file#touches-disponibles)
Version pour Xbox (XInput) :
[Voir sur GitHub](https://github.com/EloiStree/2024_08_29_ScratchToWarcraft/blob/main/README.md#xbox-xinput-version)
Malheureusement, vous ne pouvez pas simuler une manette XInput et un clavier en même temps.
Vous pouvez toutefois simuler une manette classique en même temps qu'un clavier, ainsi que d'autres périphériques.
Pour cet atelier, je propose de nous concentrer sur XInput.
Ajout d'un bouton :
Lorsque j'appuie sur le bouton jaune, il envoie
Y
pour appuyer ety
pour relâcher.(Y pour Yellow, G pour Green, B pour Blue, R pour Red.)
Si on laisse ainsi, cela fonctionnera mais avec un délai de 200 à 500 millisecondes,
le temps que l'Arduino attende une fin de ligne
\n
.Ajoutons une fin de ligne explicite :
On peut soit utiliser la convention donnée :
Exemple pour A :
1300
pour appuyer,2300
pour relâcher.Soit utiliser la convention propre à l'application, pour expérimenter.
Exemple de code pour les boutons :
Ajout des flèches :
N'oubliez pas d'ajouter les retours à la ligne.
Exemple de code pour un D-Pad à 4 ou 8 directions :
Note : Ce code ne fonctionnera pas tel quel si le texte est convertible en entier.
En effet, il sera interprété comme une valeur numérique et traité différemment.
Je vous invite donc à utiliser des chiffres comme suit :
Ajout d'un joystick :
Nous rencontrons ici une difficulté : deux joysticks nécessitent une gestion différente.
Pour le second joystick, nous allons préfixer les données avec
R
et ajouter une fin de ligne
\n
pour chaque commande.Test du terminal :
Ajoutons un terminal pour visualiser les commandes.
Connectez-vous à votre HC05, accédez au menu principal et cliquez sur "Run" pour lancer les commandes.
Avec cela, vous pouvez tester vos commandes sur un terminal Bluetooth et observer leur effet en temps réel. 🎉
Notre ami GPT 🤖 propose ceci :
Il nous reste à ajouter deux triggers (curseurs) :
La convention est A100A, mais nous allons changer pour TL100\n TR100\n
Nous pourrions contrôler le joueur avec une bulle d'air, mais vérifions avant cela que le reste fonctionne 😋👏.
A-20.01,50.45*
Avant de continuer vers les tests pour vérifier que tout cela fonctionne bien, ajoutons un Switch.
Il permettra d'activer ou non les pins pour lire les joysticks dans la vraie vie.
Vous avez l'idée :)
Je vais ajouter au code :
Mais n'hésitez pas à explorer les possibilités :
Vérifions que le code fonctionne ?
Trouver un PC ou un téléphone Android à contrôler.
Si votre ESP32 est connecté à un ordinateur, vous pouvez aller sur le site :
https://hardwaretester.com/gamepad
S'il est connecté à Android, vous pouvez installer :
https://play.google.com/store/apps/details?id=uk.co.powgames.gamecondiag&hl=en
Une fois lancée, cette application permet de voir les événements des manettes classiques, claviers et manettes Xbox.
Essayez de faire fonctionner le code d'Electronic Bluetooth avec tous les boutons de la manette sur cette application.
Si cela fonctionne, vous êtes prêt à tester cela sur vos jeux préférés et voir si les développeurs l'ont rendu compatible avec les manettes.
Si c'est le cas, "Enjoy" sinon trouvez une autre zone de test.
Car je n'ai pas implémenté le clavier Bluetooth pour le moment dans mes bibliothèques.
The text was updated successfully, but these errors were encountered: