Totem sonores Arduino RFID Processing



Github : https://github.com/scenaristeur/rfid-arduino-music-totem

La demande vient d'une intervenante 'Musique' dans une école de Neuville sur Saône.
Elle a travaillé avec des enfants et leur prof de français sur une série de 5 histoires comportant chacune 8 parties.
Les histoires ont été étudiées en français, et une image a été associée à chaque étape.
L'intervenante musique a, avec les enfants, associé à chacune des étapes/images un son ou une musique.
A ce stade, elle avait donc 40 sons et son idée était de créer un système interactif pour les enfants, avec un totem/statuette pour chaque image/son.
Que les enfants puissent poser un totem sur un capteur pour déclencher le son correspondant, avec une possibilité de combiner jusqu'à 5 sons.
Bien que nous n'ayons encore jamais testé le module RFID / NFC (NFC étant une implémentation particulière de RFID), ceci paraissait être là solution toute indiquée, avec un tag (petit autocollant) RFID collé sous chaque totem, ou une carte magnétique avec l'image collée dessus?
Relier les capteurs RFID à une carte Arduino, qui via un connecteur MIDI enverrait les informations nécessaires à un logiciel MIDI (style GarageBand) installé sur un PC.
Combien de capteurs nous faut-il?
La première idée était d'utiliser 5 capteurs, un pour chaque son/piste MIDI que l'enfant voudrait entendre.
Mais il est apparu plus réaliste dans un premier temps de n'utiliser que deux capteurs : un pour démarrer les sons, l'autre pour les stopper.
C'est le montage que nous allons mettre en œuvre maintenant.
(...)
Matériel :
- 1 Breadboard
- 1 Arduino Uno avec son câble USB
- 2 capteurs RFID
- des câbles de différentes couleurs
(Montage)
librairies à importer RFID, ...
(Code)
##################################################
/**
 * --------------------------------------------------------------------------------------------------------------------
 * Example sketch/program showing how to read data from more than one PICC to serial.
 * --------------------------------------------------------------------------------------------------------------------
 * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
 *
 * Example sketch/program showing how to read data from more than one PICC (that is: a RFID Tag or Card) using a
 * MFRC522 based RFID Reader on the Arduino SPI interface.
 *
 * Warning: This may not work! Multiple devices at one SPI are difficult and cause many trouble!! Engineering skill
 *          and knowledge are required!
 *
 * @license Released into the public domain.
 *
 * Typical pin layout used:
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno/101       Mega      Nano v3    Leonardo/Micro   Pro Micro
 * Signal      Pin          Pin           Pin       Pin        Pin              Pin
 * -----------------------------------------------------------------------------------------
 * RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
 * SPI SS 1    SDA(SS)      ** custom, take a unused pin, only HIGH/LOW required **
 * SPI SS 2    SDA(SS)      ** custom, take a unused pin, only HIGH/LOW required **
 * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
 * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
 * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
 *
 */

// explications des connections SPI https://www.youtube.com/watch?v=f_f_5cL0Pd0



#include <SPI.h>
#include <MFRC522.h>
// modifier les pins Rst(vert) et SS (jaune)
#define RST_PIN         8 //9          // Configurable, see typical pin layout above
#define SS_1_PIN        3 //10         // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 2
#define SS_2_PIN        4 //8          // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 1

#define NR_OF_READERS   2

byte ssPins[] = {SS_1_PIN, SS_2_PIN};

MFRC522 mfrc522[NR_OF_READERS];   // Create MFRC522 instance.

/**
 * Initialize.
 */
void setup() {

  Serial.begin(9600); // Initialize serial communications with the PC
  while (!Serial);    // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)

  SPI.begin();        // Init SPI bus

  for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
    mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN); // Init each MFRC522 card
    Serial.print(F("Demarre Reader "));
    Serial.print(reader);
    Serial.print(F(", "));
    mfrc522[reader].PCD_DumpVersionToSerial();
  }
}

/**
 * Main loop.
 */
void loop() {

  for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
    // Look for new cards

    if (mfrc522[reader].PICC_IsNewCardPresent() && mfrc522[reader].PICC_ReadCardSerial()) {
      Serial.print(F("Reader "));
      Serial.print(reader);
      // Show some details of the PICC (that is: the tag/card)
      Serial.print(F(": Card UID:"));
      dump_byte_array(mfrc522[reader].uid.uidByte, mfrc522[reader].uid.size);
      Serial.println();
     /* Serial.print(F("PICC type: "));
      MFRC522::PICC_Type piccType = mfrc522[reader].PICC_GetType(mfrc522[reader].uid.sak);
      Serial.println(mfrc522[reader].PICC_GetTypeName(piccType));*/

      // Halt PICC
      mfrc522[reader].PICC_HaltA();
      // Stop encryption on PCD
      mfrc522[reader].PCD_StopCrypto1();
    } //if (mfrc522[reader].PICC_IsNewC
  } //for(uint8_t reader
}

/**
 * Helper routine to dump a byte array as hex values to Serial.
 */
void dump_byte_array(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}


##################################################


Exemple de sortie reçu dans le Moniteur Serie
--> Reader 0 , card Uid : ax fg GH ok
Récupérer l'information sur le Pc
Processing peut également communiquer avec le port série de l'ordinateur sur lequel est branchée la carte Arduino.
Attention : LE MONITEUR SERIE ARDUINO DOIT ETRE FERME POUR QUE PROCESSING PUISSE L'UTILISER !
Librairie Série
(Code Processing minimal pour récupérer l'information sur le port serie)
Librairie Minin...
Test avec 4 fichiers MP3, deux porte-clés RFID et deux cartes magnétiques.
MP3 dans le dossier 'data' du sketch Processing.
Glisser les fichiers MP3 dans l'interface Processing ou les copier dans un dossier 'data' à l'intérieur du sketch Processing ou 'ajouter un fichier'
(Architecture du projet Processing)
(Code Processing amélioré avec lecture des fichiers MP3)


__________________________________________________________
// animals http://soundbible.com/tags-animal.html
// animals https://www.freesoundeffects.com/free-sounds/animals-10013/
import java.util.Map;
import processing.serial.*;
//RFID
Serial myPort;  // Create object from Serial class
String dataReading = "";
String[] data;
String action = "";
String uid = "";

//MP3
import ddf.minim.*;
AudioPlayer[] mplayer;
Minim minim;

HashMap<String, String> songs = new HashMap<String, String>();
HashMap<Integer, String> playing = new HashMap<Integer, String>();

int id_player = 0;

void setup() 
{
  size(1024, 768);
  // I know that the first port in the serial list on my mac
  // is always my  FTDI adaptor, so I open Serial.list()[0].
  // On Windows machines, this generally opens COM1.
  // Open whatever port is the one you're using.
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
  myPort.bufferUntil('\n');
  println(portName);

  minim = new Minim(this);
  mplayer=new AudioPlayer[5];

  // Putting key-value pairs in the HashMap
  songs.put("FA D7 41 09", "gibbon-monkey.mp3");
  songs.put("7B 20 92 15", "howler-monkeys.mp3");
  songs.put("A3 46 18 1A", "labrador-barking.mp3");
  songs.put("CB D8 BB 0C", "meadowlark.mp3");
}



void draw() {
  background(0);
  if ( myPort.available() > 0) {  // If data is available,
    //lecture 
    dataReading = myPort.readStringUntil('\n');
    if (dataReading != null && dataReading.length()>0) {
      println(dataReading);
      // Recuperation de l'action
      data = split(dataReading, ':');
      if (data.length == 3) {
        uid = trim(data[2]);
        if (data[0].equals("Reader 0")) {
          action = "START";
          id_player++;
          if (id_player > mplayer.length-1) {
            id_player = 0;
            //  mplayer[id_player].pause();
          }

          String mp3 = (String) songs.get(uid);
          if (mp3 != null) {
            if (mplayer[id_player]!= null) {
              mplayer[id_player].pause();
              mplayer[id_player].rewind();
            }
            mplayer[id_player] = minim.loadFile(mp3);
            mplayer[id_player].play();
            playing.put(id_player, uid);
            println("player "+id_player+" uid: "+uid+" song: "+mp3);
          } else {
            println("aucun mp3 connu pour le tag"+uid);
          }
        } else if (data[0].equals("Reader 1")) {
          action = "STOP";

          for (Map.Entry p : playing.entrySet()) {
            Integer player = (Integer) p.getKey();
            String id = (String)p.getValue();
            if (uid.equals(id)) {
              println("pause "+player);
              mplayer[player].pause();
              playing.put(player, "");
              break; // exit for loop pour ne supprimer que le premier
            }
          }
        } else {
          println("commande INCONNUE "+data[0]);
        }
      }
      println(action+" "+uid);
      for (Map.Entry p : playing.entrySet()) {
        Integer player = (Integer) p.getKey();
        String id = (String)p.getValue();
        String song = songs.get(id);
        println("player : "+player+"\t\tid: "+id+"\t\t\tsong: "+song);
      }
      println("___________________________");
    }
  }
  display();
}

void display() {

  int caseLargeur = (width-100)/mplayer.length;
  //println(caseLargeur);
  int x= 50, y = width/4, largeur=caseLargeur, hauteur = caseLargeur;
  for (int i = 0; i <mplayer.length; i++) {
    rect(x, y, largeur, hauteur);
    String id = playing.get(i);
    String song = songs.get(id);
    textSize(32);
    text("Animal "+i, x+10, y+30); 
    // fill(0, 102, 153);
    /*text("id carte "+id, x+10, y+60);
     fill(0, 102, 153, 51);*/
    if (song != null) {
      fill(0, 102, 153);
      textSize(12);
      text(song, x+10, y+60);
      //////////
          AudioPlayer p = mplayer[i];


      
      String couleur = intToARGB(song.hashCode());
     // println(couleur);
      //color col = "#"+couleur;
      
      for (int j = 0; j < p.bufferSize() - 1; j++)
      {
        line(j+x, y+50  + p.left.get(j)*50, j+1+x, y+50  + p.left.get(j+1)*50);
        line(j+x, y+150 + p.right.get(j)*50, j+1+x, y+150 + p.right.get(j+1)*50);
      }

      //stroke( 255, 0, 0 );
      stroke(unhex(couleur));
      float position = map( p.position(), 0, p.length(), 0, width );
      line( position, 0, position, height );
   
      
      
      
      ///////////
    }
    //text("id carte "+id, x+10, y+60);
    fill(0, 102, 153, 90);
    text("song "+song, x+10, y+90);


    x+=caseLargeur;
    //println(x);
  }
}


String intToARGB(int i){
    return Integer.toHexString(((i>>24)&0xFF))+
        Integer.toHexString(((i>>16)&0xFF))+
        Integer.toHexString(((i>>8)&0xFF))+
        "00"; // pas transparent
        //Integer.toHexString((i&0xFF));
}


-------------------------------------------------------------------------------------------------


Video avec les 4 sons


Il ne reste plus qu'à copier les 40 sons, les déclarer, et déclarer les 40 cartes/tags..

Commentaires