Outils pour utilisateurs

Outils du site


godot_et_le_port_serie

Godot et le port série

Présentation

Aujourd'hui, je souhaite réaliser un programme permettant, à l'aide d'un instrument, de jouer une animation sur un écran.

Les technologies impliquées sont les suivantes : un KY-038 ( ou microphone ), relié à un Arduino, qui communique par le port série avec le logiciel Godot, que je maîtrise assez bien pour créer de petites animations.

Arduino et KY-038

Le module de microphone est tout simple à utiliser : il possède quatre broches.

Les premières correspondent, comme d'habitude, à l'alimentation. La broche notée “+”, parfois appelée “Vcc” ou “Vin”, se connecte à la pin 5V de l'Arduino, tandis que la broche “G”, abréviation de “GND” (ou ground), parfois appelée “-”, se connecte à la pin “GND” de l'Arduino. Il reste deux broches sur le capteur : “DO” et “AO”. La première, Digital Out, ne m'intéresse pas : elle enverra une donnée binaire : pas de courant si le son capté est en-dessous du seuil, 5V le cas échéant. L'autre broche, Analog Out, va me permettre de récupérer une valeur relative du bruit capté, via une entrée analogique de l'Arduino, ici A0. Voici le code :

int sound_sensor = A0; // Broche d'entrée des données
int measure_length = 100; // Longueur du cycle de mesure

void setup() {
  
  pinMode( sound_sensor, INPUT ); // Broche A0 en entrée
  Serial.begin( 9600 ); // Début de la communication avec l'ordinateur

}

void loop() { // À chaque boucle

  int counter = 0; // On initialise un compteur
  long int measure = 0; // On crée une variable pour stocker nos données, assez longue pour éviter le terrible stack overflow
  
  while ( counter < measure_length ) { // Tant que l'on a pas fini de compter
    
    measure = measure + analogRead( sound_sensor ); // On ajoute la valeur lue à notre variable
    counter++; // On incrémente le compteur
    delay( 1 ); // On attends une milliseconde
    
  };

  measure = measure / measure_length; // Ici on fait la moyenne

  Serial.write( measure ); // Et on affiche tout ça dans le port série, sous Linux à priori /dev/ttyACM0 sous forme de byte.
}

Une moyenne est effectuée afin de minimiser les éventuelles incohérences.

Lien avec Godot

Je pensais qu'il existait une classe déjà prête de communication avec le port série dans Godot mais ce n'est pas le cas. À la place, j'ai trouvé ceci :

D'abord, j'ai récupéré la bonne librairie via ce projet :

https://github.com/Superwaitsum/GDSercomm

Il faut copier le fichier libsercomm.so dans les librairies de l'ordinateur :

cd /chemin/du/dossier/bin/linux64/
sudo cp libsercomm.so /usr/lib/libsercomm.so
sudo ldconfig

En trois étapes : on navigue au bon endroit, avec les droits on copie la librairie au bon endroit puis on met tout ça à jour.

Je n'ai cependant pas utilisé ce projet Godot pour tester, mais le suivant, qui avait l'air plus à jour :

https://github.com/NangiDev/GDSerCommPlugin

Il faut ouvrir le fichier project.godot dans Godot, naviguer dans le menu Projet > Paramètres du Projet > Extensions puis activer l'addon Serial Communication.

On peut ensuite lancer l'interface, régler le port sur /dev/ACM0 et le baudrate sur 9600. Cela fait planter le logiciel car le code attends une string en entrée et que nous envoyons un integer depuis l'arduino ! Il faut modifier la ligne 43 comme ceci :

readLabel.add_text(str(PORT.read()))

pour retirer l'erreur. Voilà, les données captées s'affichent dans Godot !

Créer son propre programme

Nous n'avons pas exactement fini. Nous souhaitons plutôt utiliser notre propre programme, et également faire en sorte que les valeurs affichées soient également cohérentes dans Godot ce qui n'est pas encore le cas.

Voici l'idée :

Le script du nœud KY038 est tout beau tout neuf.

Le script du nœud Serial est une copie de MenuLogic.gd.

Le script du nœud COM est Com.gd.

Le code de base est dépendant de l'interface utilisateur proposée, qui permet de sélectionner les ports et baudrates de tous les ports série, ce qui nous intéresse peu. Je vais donc modifier les fichiers afin que tout soit réglé sur le port /dev/ttyACM0 à 9600 baudrate et que les valeurs captées déclenchent automatiquement une fonction dans le script du nœud KY038, pour n'avoir plus à me soucier du processus sous-jacent de récupération des valeurs. Pour des question de flemme, le processus ne sera pas documenté, mais le résultat est le suivant :

Le script du nœud KY038 est le suivant :

extends Node2D

func new_input( value ):
	print( value )

Le script du nœud Serial est le suivant :

tool
extends Control

const SERCOMM = preload("res://addons/GDSerCommDock/bin/GDSerComm.gdns")
onready var PORT = SERCOMM.new()

var value_string = ""

func _ready():
	PORT.open( "/dev/ttyACM0", 9600, 1000, $COM.bytesz.SER_BYTESZ_8, $COM.parity.SER_PAR_NONE, $COM.stopbyte.SER_STOPB_ONE)
	PORT.flush()
	set_physics_process(true)

#_physics_process may lag with lots of characters, but is the simplest way
#for best speed, you can use a thread
#do not use _process due to fps being too high
func _physics_process(delta):
	if PORT != null && PORT.get_available()>0:
		for i in range(PORT.get_available()):
			var data = PORT.read()
			get_node("..").new_input( data )

Note : j'ai d'abord eu des valeurs incohérentes en utilisant Serial.print( measure ) dans le code Arduino. En utilisant Serial.write, les valeurs dans Godot sont bien mieux récupérées.

Pour finir, j'ai rajouté un CPUParticles2D afin que celui-ci émette un visuel quand on détecte un bruit sur le capteur :

Script du nœud KY038 :

extends Node2D

var threshold = 45;

func new_input( value ):
	if value < threshold:
		$CPUParticles2D.set_emitting( false )
	else:
		$CPUParticles2D.set_emitting( true )

Maintenant, de petites étoiles apparaissent sur l'écran quand on souffle sur le capteur ! Choupi !

godot_et_le_port_serie.txt · Dernière modification: 2020/04/04 12:37 par serge