costumescrime.net

Site d'un escrimeur, couturier, joueur de D&D

Portal Gun

icon 17/01/2017

Je m'attaque à un gros projet : un Portal Gun Je souhaite le fabriquer à taille réelle, ainsi que de lui faire émettre la lumière bleu ou orange, et les sons associés.
Pour émettre les sons, j'utilise un module SOMO II qui a besoin d'une carte micro SD, d'une alimentation 5V et d'un petit haut-parleur.

Une fois les composants achetés, j'ai regardé pour utiliser plus de son que juste les 2 sons du Portal Gun, et je me suis mis dans la tête de faire la "potato Glados" en supplément et qu'elle parle comme dans le jeu.
Il faut donc que je crée une connexion entre le module SOMO II et un arduino pour envoyer les ordres sonores.
Je rajoute un potentiomètre relié à l'arduino pour contrôler la puissance du son.

Résultat, je souhaite avoir un module arduino qui contrôle les LED orange et bleu, et qui envoie les informations sonores au SOMO II par une liaison série.

  1. Au début, aucune LED allumé.
  2. J’appuie sur le bouton poussoir gauche, la LED Bleu s'allume, et le son "Bleu" est émis. Que la LED bleu, la LED orange doit être éteinte.
  3. J'appuie sur le bouton poussoir droit, la LED orange s'allume, et le son "Orange" est émis. Que la LED orange, la LED bleu doit être éteinte.
  4. La puissance sonore doit varier en fonction du potentiomètre.
  5. Toutes les 60 a 180s, un message aléatoire de Glados patate doit être émis (tempo aléatoire à redéfinir à chaque émission d'un message Glados"

Pas besoin d'attendre un message retour sur le port série (si le message n'est pas bien recu, ce n'est pas important).


Voici ou j'en étais au 17/01/2017
// déclaration des constantes pour les noms des broches ; selon le schéma
const int btn_droit = 2;
const int btn_gauche = 3;
const int led_bleu = 10;
const int led_orange = 11;


// déclaration des variables utilisées

// le nombre qui détermine la couleur de la led
int couleur_led = 0;
// lecture de l'état des boutons (un seul à la fois mais une variable suffit)
int etat_bouton;

int memoire_droit = HIGH; // état relâché par défaut
int memoire_gauche = HIGH;


/* initilisation des broches en entrée/sortie */
void setup()
{
   pinMode(btn_droit, INPUT);
   pinMode(btn_gauche, INPUT);
   pinMode(led_bleu, OUTPUT);
   pinMode(led_orange, OUTPUT);
}

void loop()
{
   // lecture de l'état du bouton droit
   etat_bouton = digitalRead(btn_droit);

   // Si le bouton a un état différent que celui enregistré ET
   // que cet état est "appuyé"
   if((etat_bouton != memoire_droit) && (etat_bouton == LOW))
   {
       // on indique quelle LED on allume
       couleur_led = 1;
   }

   // on enregistre l'état du bouton pour le tour suivant
   memoire_droit = etat_bouton;


   // et maintenant pareil pour le bouton gauche
   etat_bouton = digitalRead(btn_gauche); // lecture de son état

   // Si le bouton a un état différent que celui enregistré ET
   // que cet état est "appuyé"
   if((etat_bouton != memoire_gauche) && (etat_bouton == LOW))
       {
       // on indique quelle LED on allume
       couleur_led = 2;
   }
   // on enregistre l'état du bouton pour le tour suivant
   memoire_gauche = etat_bouton;

   // appel de la fonction affiche() que l'on aura créée
   // on lui passe en paramètre la valeur de la couleur de LED à éclairer
   affiche(couleur_led);
}

void affiche(int valeur_recue)
{    if(valeur_recue == 0)
   {
       digitalWrite(led_bleu, HIGH);
       digitalWrite(led_orange, HIGH);
       }
   if(valeur_recue == 1)
   {
       digitalWrite(led_bleu, LOW);
       digitalWrite(led_orange, HIGH);
       }
   if(valeur_recue == 2)
   {
       digitalWrite(led_bleu, HIGH);
       digitalWrite(led_orange, LOW);
       }
}

MAJ du 20/01/2017 : J'ai fini le programme, il fonctionne exactement comme je le souhaitais, mais je rajouterais peut-être quelques fonctions, à voir.
#include <SoftwareSerial.h>
// déclaration des constantes pour les noms des broches ; selon le schema
const int btn_gauche = 2;
const int btn_droit = 3;
const int led_bleu = 10;
const int led_orange = 11;
const int btn_glados = 7;
const int Rx_pin = 4;
const int Tx_pin = 5;
// le potentiomètre, branché sur la broche analogique 0
const int potar = 0;
// nombre de pistes audio de Glados -- A MODIFIER --
const int nombre_pistes = 20;

// déclaration des variables utilisées

//variable pour stocker la valeur lue après conversion
int valeurLue;
int piste;
//on convertit cette valeur en une tension
float valeur_son;

// le nombre qui détermine la couleur de la led
int couleur_led = 0;

long duree_seconde = 15;  // premiere duree forcee a 15s
long duree_milis = duree_seconde * 1000;
long tempoDepart = 0;  // on initialise la tempo depart
int memoire_son = 0;

// lecture de l'état des boutons (un seul à la fois, mais une variable suffit)
int etat_bouton;

int memoire_droit = HIGH; // etat relâche par defaut
int memoire_gauche = HIGH;

// create the object for the virtual serial port. In this case, it's called Somo
SoftwareSerial Somo(Rx_pin,Tx_pin);
// define a structure for holding the bytes that will be passed to the SOMO
typedef struct _ControlMsg
{
  byte  start;
  byte  cmd;
  byte  feedback;
  byte  para1;
  byte  para2;
  byte  checksum1;
  byte  checksum2;
  byte  end;
} ControlMsg;

/* initialisation des broches en entrée/sortie */
void setup()
{
  pinMode(btn_gauche, INPUT_PULLUP);
  pinMode(btn_droit, INPUT_PULLUP);
  pinMode(led_bleu, OUTPUT);
  pinMode(led_orange, OUTPUT);
  pinMode(btn_glados, INPUT_PULLUP); 
  Initialize_SOMO();
  Serial.begin(9600);
}

void loop()
{
// lecture de l'état du bouton gauche
  etat_bouton = digitalRead(btn_gauche);

  // Si le bouton a un état différent que celui enregistre ET
// que cet état est "appuyé"
  if((etat_bouton != memoire_gauche) && (etat_bouton == LOW))
  {
// on indique quelle LED on allume
    couleur_led = 1;
    Play_Gun(1);
    Serial.println("Bouton gauche activé, la led bleu s'allume");
  }

// on enregistre l'état du bouton pour le tour suivant
  memoire_gauche = etat_bouton;

// et maintenant pareil pour le bouton droit
  etat_bouton = digitalRead(btn_droit); // lecture de son etat

  // Si le bouton a un état différent que celui enregistre ET
// que cet état est "appuyé"
  if((etat_bouton != memoire_droit) && (etat_bouton == LOW))
    {
// on indique quelle LED on allume
    couleur_led = 2;
    Play_Gun(2);
    Serial.println("Bouton droit activé, la led orange s'allume");
  }
// on enregistre l'état du bouton pour le tour suivant
  memoire_droit = etat_bouton;

// appel de la fonction affiche() que l'on aura créée
// on lui passe en paramètre la valeur de la couleur de LED a éclairé
  affiche(couleur_led);
  
// Si le bouton Glados est actif,
  if ( digitalRead(btn_glados) == LOW ) 
  {
    
// Et si il s'est écoulé entre 60 et 180 secondes,
    if ( ( millis() - tempoDepart ) >= duree_milis )
    {
      
// Alors on lance une des musiques de glados
      piste = random(1, nombre_pistes);
      Play_Glados(piste);
      Serial.print("Glados va jouer la piste n ");
      Serial.println(piste);

// Et on redemare la temporisation pour ne pas afficher ce message une seconde fois
      duree_seconde = random(60, 120);
      duree_milis = duree_seconde * 1000;
      tempoDepart = millis();
      Serial.print("Prochaine musique dans ");
      Serial.print(duree_seconde);
      Serial.println(" secondes");
      Serial.println("");
    }
  }
  
//on convertit en nombre binaire la tension lue en sortie du potentiomètre
  valeurLue = analogRead(potar);

//on traduit la valeur brute en valeur du son (1-30)
  valeur_son = map(valeurLue, 1, 1024, 1, 30);
  
//si la valeur du son est modifie, on sauvegarde cette valeur et on émet la valeur au module SOMO II
  if (valeur_son != memoire_son)
  {
    memoire_son = valeur_son;
    Envoi_son(memoire_son);
    Serial.print("la valeur du son est de : ");
    Serial.println(memoire_son);
    Serial.println("");
    }
    
}
// Fonction d'initialisation du SOMO II
void Initialize_SOMO()
{
// initialise le module SOMO II
  Somo.begin(9600);
  delay(500);
}

void affiche(int valeur_recue)
{ if(valeur_recue == 0)
  {
    digitalWrite(led_bleu, HIGH);
    digitalWrite(led_orange, HIGH);
  }
  if(valeur_recue == 1)
  {
    digitalWrite(led_bleu, LOW);
    digitalWrite(led_orange, HIGH);
    }
  if(valeur_recue == 2)
  {
    digitalWrite(led_bleu, HIGH);
    digitalWrite(led_orange, LOW);
  }
}

// Cette fonction permet de lire les fichiers du Portal Gun
void Play_Gun(byte gun)
{
  ControlMsg ctrlMsg;   // structure
  // set variables for playing a track
  byte cmd = 0x0F;     // sets the "Play a specified folder & track" command
  byte feedback = 0;   // sets the feedback requirement to off
  byte para1 = 1;      // sets it to folder "01" on the microSD card
  byte para2 = gun;  // sets the track number  (1 to 255)
  // populate structure with the bytes
  ctrlMsg.start = 0x7E;    //  always use this starter byte
  ctrlMsg.cmd = cmd;  
  ctrlMsg.feedback = feedback; 
  ctrlMsg.para1 = para1;  
  ctrlMsg.para2 = para2;  
  // Sending instructions to the SOMO requires the use of a checksum
  // Checksum (2 bytes) = 0xFFFF – (CMD + Feedback + Para1 + Para2) + 1
  word chksum = 0xFFFF - ((word)cmd + (word)feedback + (word)para1 + (word)para2) + 1;  
  ctrlMsg.checksum1 = (byte)(chksum >> 8); // upper 8 bits
  ctrlMsg.checksum2 = (byte)chksum; // lower 8 bits
  ctrlMsg.end = 0xEF;     // always use this end byte
  // Now we write the structure to the SOMO MP3 Module
  Somo.write((const byte*)&ctrlMsg, sizeof(ctrlMsg));
  Somo.flush();
}

// Cette fonction permet de lire les fichiers de Potato Glados
void Play_Glados(byte track)
{
  ControlMsg ctrlMsg;   // Create structure
  // set variables for playing a track
  byte cmd = 0x0F;     // sets the "Play a specified folder & track" command
  byte feedback = 0;   // sets the feedback requirement to off
  byte para1 = 2;      // sets it to folder "01" on the microSD card
  byte para2 = track;  // sets the track number  (1 to 255)
  // populate structure with the bytes
  ctrlMsg.start = 0x7E;    //  always use this starter byte
  ctrlMsg.cmd = cmd;  
  ctrlMsg.feedback = feedback; 
  ctrlMsg.para1 = para1;  
  ctrlMsg.para2 = para2;  
  // Sending instructions to the SOMO requires the use of a checksum
  // Checksum (2 bytes) = 0xFFFF – (CMD + Feedback + Para1 + Para2) + 1
  word chksum = 0xFFFF - ((word)cmd + (word)feedback + (word)para1 + (word)para2) + 1;  
  ctrlMsg.checksum1 = (byte)(chksum >> 8); // upper 8 bits
  ctrlMsg.checksum2 = (byte)chksum; // lower 8 bits
  ctrlMsg.end = 0xEF;     // always use this end byte
  // Now we write the structure to the SOMO MP3 Module
  Somo.write((const byte*)&ctrlMsg, sizeof(ctrlMsg));
  Somo.flush();
}

// Cette fonction envoie la valeur du son
void Envoi_son(byte sound)
{
  ControlMsg ctrlMsg;   // Create structure
  // parametre pour le son
  byte cmd = 0x06;
  byte feedback = 0;   // sets the feedback requirement to off
  byte para1 = 0;      // sets it to modifie sound
  byte para2 = sound;  // sets the sound  (1 to 30)
  // populate structure with the bytes
  ctrlMsg.start = 0x7E;    //  always use this starter byte
  ctrlMsg.cmd = cmd;  
  ctrlMsg.feedback = feedback; 
  ctrlMsg.para1 = para1;  
  ctrlMsg.para2 = para2;  
  // Sending instructions to the SOMO requires the use of a checksum
  // Checksum (2 bytes) = 0xFFFF – (CMD + Feedback + Para1 + Para2) + 1
  word chksum = 0xFFFF - ((word)cmd + (word)feedback + (word)para1 + (word)para2) + 1;  
  ctrlMsg.checksum1 = (byte)(chksum >> 8); // upper 8 bits
  ctrlMsg.checksum2 = (byte)chksum; // lower 8 bits
  ctrlMsg.end = 0xEF;     // always use this end byte
  // Now we write the structure to the SOMO MP3 Module
  Somo.write((const byte*)&ctrlMsg, sizeof(ctrlMsg));
  Somo.flush();
}

Ce code est libre d'utilisation, à vous d'en faire ce que bon vous semble ;)

icon Tags de l'article :

Aucun commentaire

icon Flux RSS des commentaires de cet article