Précédente Accueil Suivante

 

Accueil
Le projet IRBOT
Chassis roues
Servomoteur
Modif servos
Test servos
Le radar IR
Premiers pas robot
Détection collision
Télécommander
Test RC5
IRBOT et RC5
Mémo parcours
Mise en veille
Vers PIC16F628
Borne recharge
Compilateur CCS
Modif matérielle
Recharge du robot
Bip Bip ...
En musique
Vidéos
Téléchargements
Carte développ.
Liens Affiliation

Jouer de la musique

Ah, enfin on y vient. Il va y avoir de l'ambiance.

Voilà, on va tenter de faire jouer un morceau de musique à IRBOT en plus de tout ce qu'il doit déjà faire.

On aurai pu utiliser un générateur de mélodie tout fait, tel que l'UM66T-20L par exemple. Mais c'est beaucoup plus amusant d'écrire son propre générateur de mélodie, d'autant plus qu'on a un microcontrôleur à notre disposition.

Dans le post précédent, on a vu comment générer une tonalité précise (le Bip) à l'aide de la fonction son (val, durée) qui utilise le générateur de fréquence PWM.
Eh ben, pour jouer de la musique on va simplement appeler le fonction son() pour chaque note de la partition musicale.

Tout d'abord, on définie la gamme des notes de 2 octaves dans un tableau statique. Un tableau statique a l'avantage d'être stocké dans la mémoire flash. Il n'utilise pas de RAM. La RAM est précieuse, il faut l'économiser.

Voici la définition du tableau des notes


// NOTE FREQUENCE ---> val=5000000/(frequence*16)

// Octave0 Octave1
const int C_NOTE[2] ={ 149, 74};
const int Db_NOTE[2] ={ 140, 70};
const int D_NOTE[2] ={ 133, 66};
const int Eb_NOTE[2] ={ 125, 62};
const int E_NOTE[2] ={ 118, 59};
const int F_NOTE[2] ={ 111, 55};
const int Gb_NOTE[2] ={ 105, 52};
const int G_NOTE[2] ={ 99, 49};
const int Ab_NOTE[2] ={ 94, 47};
const int A_NOTE[2] ={ 88, 44};
const int Bb_NOTE[2] ={ 83, 41};
const int B_NOTE[2] ={ 79, 39};


Comme précedemment, val est calculée à l'aide de la formule val= 5000000 / (frequence *16 )

149 correspond à une fréquence de 2093 Hz, le Do.

Voilà, on a notre tableau des notes, il ne reste plus qu'à faire un tableau de la partition de notre mélodie.
J'ai choisi Joyeux Anniversaire, c'est peut-être pas très original, vous avez surement mieux à me proposer.

Le tableau de la partition, également stocké en mémoire flash.


#define TAILLE_JOYEUX 25

const struct PARTITION // DUR = temps / 24ms
{
int NOTE;
int DUR;
} JA [TAILLE_JOYEUX] = {

C_note[0],15, C_note[0],4, D_note[0],21, C_note[0],21, F_note[0],21, E_note[0],37,
C_note[0],15, C_note[0],4, D_note[0],21, C_note[0],21, G_note[0],21, F_note[0],37,
C_note[0],15, C_note[0],4, C_note[1],21, A_note[0],21, F_note[0],21, E_note[0],21, D_note[0],37,
Bb_note[0],15, Bb_note[0],4, A_note[0],21, F_note[0],21, G_note[0],21, F_note[0],50};


Le tableau de la partition est un tableau à 2 dimensions : note et durée
La note pointe sur le tableau des notes. La durée est exprimée en fraction de 24ms (des essais ont révélé ce chiffre). La durée est variable et correspond aux blanches, noires etc ... de la partition pour ceux qui ont des notions de solfège.

Voilà, on a notre tableau des notes et le tableau de la partition. Il ne reste plus qu'à créer un séquenceur qui va dérouler la partition.

Comme d'habitude, on va utiliser la routine d'interruption qui est appelée toutes les 20ms (environ).
On y rajoute notre bout de programme qui fait office de séquenceur.


if (MUSIQUE) {
if (!TONE) { // si pas de son en cours
son(JA[IX_NOTE].NOTE, JA[IX_NOTE].DUR);
CPT_PAUSE=3; // 3*24ms
MUSIQUE=0;
if(++IX_NOTE==TAILLE_JOYEUX) {
IX_NOTE=0;
CPT_PAUSE=82; // pause 2"
}
}
}
else {
if (CPT_PAUSE) {
if (!--CPT_PAUSE) MUSIQUE=1;
}
}


IX_NOTE est l'index de la partition, il est incrémenté à chaque note jouée. Avant de jouer la note suivante,on attend que la note en cours soit terminée. Et on met une pause de 75ms (environ) entre 2 notes.
Lorqu'on arrive en fin de partition, on recommence au début.
On appelle donc la fonction son() avec les paramètres de chaque note.

La fonction son pour rappel


int1 son(int val, int duree) {

if (TONE) return 1;

TONE=1;
CPT_TONE=duree;

setup_ccp1(CCP_PWM); // Configure CCP1 en PWM
setup_timer_2(T2_DIV_BY_16, val, 1); // définie la période
set_pwm1_duty(25);

}


Voilà, c'est donc le génrateur PWM qui émet soigneusement la bonne fréquence vers le buzzer.

Prochain post : la vidéo

On va encore rajouter un petit plus. On a une touche HP sur notre télécommande qui ne sert à rien.
Autant la rajouter à notre prog. Premier appui sur HP, on coupe la musique, deuxième appui on remet.

Voici le petit bout de prog à rajouter dans la fonction switch pour prendre en compte la touche HP.


case 13: // Touche HP
if (MUSIQUE || CPT_PAUSE) {
MUSIQUE=0;
CPT_PAUSE=0;
setup_ccp1(CCP_OFF);
}
else {
MUSIQUE=1;
CPT_PAUSE=3;
IX_NOTE=0;
}
delay_ms(100); // car la télécommande envoie plusieurs trame
return;


Et pour clore ce post, la vidéo de démonstration de la musique (1,3M)

http://pro.wanadoo.fr/yves.heilig/Forum/IRBOT/Videos/irbot_musique.avi


Si vous avez des idées sur des mélodies originales, faites le moi savoir.

 

Précédente Accueil Suivante