Catégories
jeu arduino projet matlab

Projets Matlab & Microcontrôleur #6: Manette de jeu infrarouge avec Arduino 2/2

Manette de jeu infrarouge avec Arduino 1

Objectifs

Le présent article et la partie 2/2 du projet du jeu labyrinthe avec Arduino et Matlab (voir la partie 1/2). Nous avons abordé dans la première partie l’interface du jeu avec Matlab et comment générer un labyrinthe aléatoire en utilisant une librairie Matlab. Ici on va se focaliser particulièrement sur la liaison télécommande IR-Arduino et Arduino-Matlab. On fera également une mise à jour du programme matlab pour l’adapter à la manette infrarouge. Les objectifs du projet sont les suivants :

  • Savoir transférer les données entre Arduino et Matlab
  • Savoir utiliser une télécommande IR
  • Se familiariser à la programmation matlab
  • Etc.

Vidéo démonstration

Principe de fonctionnement

En résumé la carte arduino est analogue à une manette de jeu infrarouge sans fil constituée de 4 touches. Chaque touche sert à contrôler le déplacement du joueur dans l’interface Matlab (droite, fauche, haut et bas). La carte dispose également de quatre LED indiquant la touche active. La LED s’allume pendant 200 ms quand l’utilisateur appuie sur la télécommande IR. Ci-dessous la configuration des touches de la télécommande IR et le code correspondant (voir le projet commande IR d’un moteur à CC) .

touches manette IR

Programme Arduino

Pinout des composants avec Arduino (voir le schéma au début de l’article)

  • Récepteur IR : 11
  • LED bleue:  2
  • LED rouge: 3
  • LED verte: 4
  • LED jaune: 5

Codage des touches et liaison avec Matlab

La carte Arduino scrute le récepteur en boucle. Lorsqu’une touche de la télécommande est active, la carte Arduino communique un code sur 1 octet au logiciel Matlab via la liaison série. En effet, chaque touche de la télécommande dispose d’un code sur 3 octets. Lorsque le récepteur détecte le code, il indique la présence d’une touche. Dans notre cas uniquement 4 touches seront utilisées. Ci-dessous le tableau récapitulatif des codes reçus par la télécommande et ceux envoyés à Matlab :

Touche de la télécommande Fonction Code envoyé par la télécommande (HEX) Code envoyé à Matlab (Décimal)
« 2 » Up 0xFF18E7 150
« 8 » Down 0xFF4AB5 160
« 4 » Left 0xFF10EF 170
« 6 » Right 0xFF5AA5 180
Autres Waiting Others 99

Programme

#include "IRremote.h"


// Numéro du pin sortie du récepteur
long int res_val;
const int receiver = 11;

// Indicateurs manette
const int UpLED = 2;
const int DownLED = 3;
const int LeftLED = 4;
const int RightLED = 5;

// Déclaration d'un objet IRrecv
IRrecv irrecv(receiver);
decode_results results;

void setup()
{
// Init RS232
Serial.begin(9600);

// Init Indicateurs manette
pinMode(UpLED, OUTPUT);
pinMode(DownLED, OUTPUT);
pinMode(LeftLED, OUTPUT);
pinMode(RightLED, OUTPUT);

// Init du récepteur
irrecv.enableIRIn();

// Initialisation
digitalWrite(UpLED, LOW);
digitalWrite(DownLED, LOW);
digitalWrite(LeftLED, LOW);
digitalWrite(RightLED, LOW);
}

void loop()
{
// Lecture de la télécommande
if (irrecv.decode(&results))
{
// Récupération du code
res_val = results.value;

// Réception de la nouvelle valeur
irrecv.resume();
}

// Envoie la commande à Matlab
ManetteTocuhe(res_val);

// Init
res_val=0;
}

void InitLEDs(void)
{
digitalWrite(UpLED, LOW);
digitalWrite(DownLED, LOW);
digitalWrite(LeftLED, LOW);
digitalWrite(RightLED, LOW);
Serial.println(99,DEC); // Waiting...
delay(200);
}
void ManetteTocuhe(long Chan_code)
{
switch(res_val)
{
case 0xFF18E7: // Up
digitalWrite(UpLED, HIGH);
digitalWrite(DownLED, LOW);
digitalWrite(LeftLED, LOW);
digitalWrite(RightLED, LOW);
Serial.println(150,DEC);
delay(200);
break;

case 0xFF4AB5: // Down
digitalWrite(UpLED, LOW);
digitalWrite(DownLED, HIGH);
digitalWrite(LeftLED, LOW);
digitalWrite(RightLED, LOW);
Serial.println(160,DEC);
delay(200);
break;

case 0xFF10EF: // Left
digitalWrite(UpLED, LOW);
digitalWrite(DownLED, LOW);
digitalWrite(LeftLED, HIGH);
digitalWrite(RightLED, LOW);
Serial.println(170,DEC);
delay(200);
break;

case 0xFF5AA5: // Right
digitalWrite(UpLED, LOW);
digitalWrite(DownLED, LOW);
digitalWrite(LeftLED, LOW);
digitalWrite(RightLED, HIGH);
Serial.println(180,DEC);
delay(200);
break;

default:
InitLEDs();
}
}

Programme Matlab

Test de l’interface série (voir la vidéo)

Le script Matlab TestManette.m sera utilisé pour valider le bon fonctionnement de l’interface série. Son objectif est la lecture et l’affichage en boucle du contenu de l’interface série au format entier. La carte Arduino envoie le code « 99 » lorsque aucune touche n’est actionnée et un ensemble de 4 valeurs (voir le tableau ci-dessus) au moment d’appui sur  la touche. Le programme ci-dessous affiche la valeur acquise  lorsqu’elle est différente du « 99 ».

%% Open Serial Port

SerialCOM = Open(); % Open new port

%% Read data from Serial port

while(1)
% Read data
DataArduino = fscanf(SerialCOM,'%d');
if(DataArduino~=99)
DataArduino
end
end

%% Port Delete (Previous port if exist)

Delete(SerialCOM);

test de l'interface série

Mises à jour du programme précédent

Le programme est identique au celui de  la partie 1/2. Nous avons effectué une légère mise à jour. Nous avons ajouté une boucle infinie au début de la boucle principale (while(1)). Elle bloque le programme en attendant un appui sur une touche de la télécommande (voir ci-dessous).

while(1)
...
% Read data from serial port (attente)
while(1)
DataArduino = fscanf(SerialCOM,'%d');
if (DataArduino~=99)
break;
end;
end;
...
end

Nous avons aussi utilisé une nouvelle fonction ManetteVal() qui permet de convertir la valeur acquise en un vecteur de taille quatre. Chaque case du vecteur est liée  à un déplacement du joueur dans le labyrinthe (voir partie ½ du projet). Lorsqu’un champ est égal à « 1 », il indique l’activation d’un déplacement. Les champs sont égaux à « 1 » ([1 1 1 1]) dans le cas contraire (voir le script ManetteVal.m).

function Manette = ManetteVal( DataArduino )

switch DataArduino
case 150 % UP
Manette=[1 0 0 0];
case 160 % DOWN
Manette=[0 1 0 0];
case 170 % LEFT
Manette=[0 0 0 1];
case 180 % RIGHT
Manette=[0 0 1 0];
otherwise
Manette=[1 1 1 1];
end
end

Le programme principal (main.m)

%% Open Serial Port

SerialCOM = Open(); % Open new port

%% Programme principal

% Params Labyrinthe
sz=10;
tile_sz=100;
tangling_steps=300;
growing_steps=900;

% Génération LABY
[elements,t_set] = Maze_gen( sz,tangling_steps,growing_steps);
img_maze = Plot_maze( elements,t_set,tile_sz);

% Taille du joueur NxN
N=20;

% Déplacement en pixel
Pas=round(N/2);

% Coordonnées de la position initiale du joueur (x0, y0)
img_maze0=img_maze; im_rgb=((im2uint8(img_maze0)));
pix =[236 28 36];
x_y=GetPixel(im_rgb, pix);
Start_y_0=x_y(1);Start_y=Start_y_0;
Start_x_0=x_y(2); Start_x=Start_x_0;

% Manette
Manette=ones(1,4);
Seuil_outZone=0.3;

% Positionner le joueur sur (x0, y0)
img_maze0(Start_y_0:Start_y_0+N-1,Start_x_0:Start_x_0+N-1,:)=128*ones(N,N,3);
im_affich=imresize(img_maze0,[512 512]);
imshow(im_affich); title('Maze size 10x10'); axis square;

% Compteur pas vers la cible
Cmp_cible=0;
Out_zone_pinal=2;
figure(1);

while(1)

% Read data from serial port (attente)
while(1)
DataArduino = fscanf(SerialCOM,'%d');
if (DataArduino~=99)
break;
end;
end;

% Obtenir le vecteur Manette
Manette = ManetteVal( DataArduino );

% Extraction des valeurs
Down =Manette(1);
Up=Manette(2);
Right =Manette(3);
Left=Manette(4);

% Déplacement
if Up~0
Start_y=Start_y_0+Pas;
elseif Down~0
Start_y=Start_y_0-Pas;
if Start_y <=0
Start_y=1;
end;
end;
if Right~0
Start_x=Start_x_0+Pas;
elseif Left~0
Start_x=Start_x_0-Pas;
if Start_x <=0
Start_x=1;
end;
end;

% Calcul de la valeur moyenne de la position actuelle

% Extraction du bloc NxN
im_0= img_maze0(Start_y:Start_y+N-1,Start_x:Start_x+N-1,:);

% Conversion RGB => Gray
im_0=rgb2gray(im_0);

% Caclul de la valeur moyenne
mean_pixel=mean(im_0(:));

% Gestion du compteur: Incrémentation ou Pénalité
if(mean_pixel < Seuil_outZone)
% Affichage
img_maze0(Start_y:Start_y+N-1,Start_x:Start_x+N-1,:)=128*ones(N,N,3);
im_gray=im2uint8(imresize(img_maze0,[512 512]));
imshow(im_gray); title('Maze size 10x10'); axis square;

% Mise à jour
Start_y_0=Start_y;
Start_x_0=Start_x;
Cmp_cible=Cmp_cible+1;
else
Cmp_cible=Cmp_cible+Out_zone_pinal;
end

% Affichage score
disp('Votre compteur:');
disp(Cmp_cible);

% Délai & Init
pause(0.5);
Manette=ones(1,4);
img_maze0=img_maze;
end

%% Port Delete (Previous port if exist)

Delete(SerialCOM);

Photos du projet

Projet Manette de jeu infrarouge avec Arduino (2)

Photos Projet Manette de jeu infrarouge avec Arduino (3)

Photos Projet Manette de jeu infrarouge avec Arduino (2)

Photos Projet Manette de jeu infrarouge avec Arduino (1)

Téléchargement

Tout les projets Matlab & µC

 

Laisser un commentaire