Coach Dance

De Wiki de Projets IMA

Présentation

L'apprentissage de la danse peut poser certains problèmes aux débutants. Un des problèmes majeurs rencontré concerne la synchronisation des mouvements sur le rythme de la musique. De nombreux débutants n'entendent pas le rythme soit parce qu'ils ne connaissent pas bien le type de musique (e.g. salsa) soit parce que la coordination des mouvements (bras et jambes) leur demandent de gros efforts cognitifs.

L'objectif du projet consiste à aider les danseurs débutants en donnant les indications de rythme et de mouvement. Pour cela, vous devez développer un système portable (type wearable computer) qui devra :

  • détecter de manière automatique le rythme de la musique. Dans un premier temps, nous ciblerons deux danses, la salsa et le rock 6 temps. Le type de danse sera indiqué au système afin de "simplifier" la reconnaissance
  • en fonction du rythme et de la danse, activer un des vibreurs qui seront disposé sur le danseur. Dans un premier temps, un vibreur sera installé sur chacun des mollets afin d'indiquer quel est le pied à bouger. Si le temps le permet, il sera possible d'étendre le système au mouvement des bras ou à d'autres danses.

Préparation du projet

Matériel

  • 1 arduino lilypad (disponible) ;
  • 4 vibreurs (à commander) ;
  • 1 micro portable (à commander) [1];
  • -> un cable jack par micro pour la connection à une plateforme Altium (disponibilité ?)
  • pour la connection Altium/Zigbee : puce Zigbee/cable(adaptateur usb)
  • Des morceaux de musique Salsa et Rock (à commander...XD);

Danses

Les deux danses visées dans un premier temps sont la salsa (style cubain, http://fr.wikipedia.org/wiki/Salsa) et le rock 6 temps (http://fr.wikipedia.org/wiki/Rock_%C3%A0_six_temps). Le système devra permettre de sélectionner la danse et le sexe de la personne (les pas de la fille sont inversés par rapport à ceux du garçon)

Avancement du projet

Première Séance (28/02/2011) -- 2h

Nous avons trouvé un lien pour un montage de détection des beats par minute (d'une basse) dans une chanson. Ce montage devra sûrement être adapté pour la salsa car le rythme est repéré par le claquement des claves de fréquence plus hautes que les basses.

lien pour du montage de détection bpm
http://www.sonelec-musique.com/electronique_realisations_compteur_tempo_001.html

idée à développer: filtre numérique passe bande à tester sur 2 sons wav différents... (fft sur un fichier wav avec matlab puis calcul du filtre)

lien pour le câblage d'un micro 
http://www.sonelec-musique.com/electronique_bases_alim_micro_electret.html

Etapes prévues:

Test de la méthode de détection des beats par minute 
Nous voulons trouver une façon de faire le traitement numérique avec le microcontrôleur du LilyPad (ATmega328V) pour éviter d'avoir à concevoir un circuit imprimé en parallèle avec un montage à amplificateur opérationnel.
Phase de développement 
Après avoir trouvé la méthode finale de détection des beats par minute nous devrons concevoir un programme permettant de traiter ces informations et surtout adaptable à plusieurs sortes de musique
Partie pratique
Conception du vêtement intelligent

Deuxième Séance (3/03/2011) -- 2h

Test de traitement FFT avec Matlab d'un fichier wav a résulté à un échec. Test avec un programme développé par un étudiant de Supelec a échoué également. Nous nous sommes donc décidé à effectuer un traitement avec une plateforme Altium et utilisation de arduino / lilypad pour la communication zigbee et la gestion des vibreurs.

les micros dont nous avons besoin sont disponibles il nous manquera juste des composants type résistance condensateur etc...

Prochaine séance: Essai avec la plateforme Altium (Maxime) recherche d'info sur Zigbee (Catherine)


Troisieme Séance (3/03/2011)-- 2h

Test sur la plateforme Altium :

  • Mise en place du programme Altium : conception du schematic (indique quels composants de la nanoboard utiliser) et d'un code C simple.
  • Un micro est connecté sur la plateforme Altium. On a essayé de récupérer le signal numérisé, pour pouvoir ensuite le traiter. Les résultats obtenus ne sont pas satisfaisants.

Quatrième Séance (7/03/2011)-- 2h

Arduino

Pour communiquer via Zigbee il suffit de
-pluger une plateforme zigbee sur arduino : cette manoeuvre permet d'utiliser zigbee comme un port série en la branchant en usb sur un pc
-brancher une autre puce zigbee avec un câble miniusb-usb sur un autre port usb du pc

On peut ensuite faire communiquer les puces entre elles en faisant des read() et write() sur les descripteurs de fichiers associés (test non encore effectué à faire à la prochaine séance)


Plateforme Altium

  • Je comprends comment faire pour enregistrer, notamment l'utilitée et le fonctionnement de la fonction get_audio() d'Altium. Celle-ci enregistre dans un buffer d'entiers les valeurs en sortie du CAN d'Altium.
  • Je m'aide d'un programme exemple fourni avec le soft Altium Designer
  • Probleme : les valeurs retournées par l'enregistrement ne sont pas satisfaisantes.

Cinquième Séance (10/03/2011) -- 2h

Arduino

Programme arduino et zigbee.c développés et fonctionnnent. A la prochaine séance il faudra voir comment on peut envoyer le numéro du vibreur à actionner et le traitement qui sera fait par lilypad en fonction du numéro reçu par la puce zigbee sur le t-shirt.


Plateforme Altium

  • Identification du problème sur les valeurs retournées par l'enregistrement : l'enregistrement est réalisé sur 8 bit, mais le stockage est fait dans un int (integer) donc sur 4 octets (32 bits). Quand on cast les entiers enregistrés, les valeurs retournées sont plus probables. Il y a cependant des valeurs de 'bruit' ou en tout cas abérentes supérieures à 200. (les valeurs sont codées de 0 à 255)
  • Je décide d'utiliser directement l'exemple d'Altium et de le modifier pour mon projet

Sixième Séance (14/03/2011) -- 2h

Arduino

Méthode retenue pour l'envoi du numéro de vibreur: branchement de 4 pins de l'arduino sur la platine et la platine altium envoi un signal état haut pour l'activation d'un des 4 vibreurs (pin 1 à l'état haut : activation du vibreur 1, idem pour les 3 autres vibreurs), une fois le numéro de pin reçu on l'envoi via la puce Xbee présente sur arduino.

Plateforme Altium :
Je travaille toujours sur la récupération des données que je recois sur le micro.

Septième Séance (17/03/2011) -- 2h

Arduino

Il va falloir brancher la puce Xbee réceptrice sur le Lilypad (câble mini-USB vers connectique Lilypad commandé). il faut d'abord faire les tests sur plateforme Arduino (câblage de Lilypad avec du fil à coudre fastidieux et long à modifier).

Début de la programmation de commande des vibreurs: Les rythmes du rock 6 temps sont les suivants: 1,2, 3 et 4,5 et 6. pour le garçon cela revient à faire gauche(1), droite (2),gauche(3)-droite(et)-gauche(4), droite(5)-gauche(et)-droite(6). Idem pour la fille mais en miroir. On remarque qu'entre les temps 3 et 4, puis 5 et 6, il y a un demi-temps à marquer qui n'est pas indiqué par un beat. Il faut donc déterminer le temps qui sépare 2 beats et prévoir une vibration supplémentaire pour le demi-temps "et". La fonction millis() sous Arduino permet d'obtenir le temps qui s'est écoulé depuis le lancement du programme en millisecondes. Pour obtenir le demi-temps il suffit de stocker le temps lors du pas 1 et lors du pas 2 puis de diviser la différence par 2 pour obtenir la durée d'un demi-temps. Sachant que l'on actionne le vibreur pendant un certain temps il faudra déduire ce temps du demi-temps pour actionner le vibreur suivant.

NB: trouver une solution pour sélectionner le mode femme ou le mode homme (platine Lilypad interrupteur? http://www.lextronic.eu/doc/produit/img1_18685.jpg)

plateforme Altium :

  • J'arrive à recevoir les données audio du micro et à les faire jouer par la nanoboard. Le résultat est plutôt satisfaisant, on discerne assez bien ce que l'on envoie sur le micro, bien que la qualité de retour soit médiocre.
  • Dorénavant je travaillerais en insérant directement par câble Jack les données audio sur l'entrée casque de la nanoboard, pour limiter le bruit au maximum.

Huitième Séance (21/03/2011) -- 2h

Arduino

Fin de la programmation du code à implanter dans le Lilypad idée trouvée pour sélectionner mode homme ou femme: un bouton poussoir et une LED RVB qui change de couleur en fonction du mode sélectionné (orange: aucun mode, bleu: homme, rose: femme)

Plateforme Altium :

Affichage de 300 coefficients. Une 50aine est utile
  • Implémentation d'un filtre à réponse impulsionnelle finie (RIF).
  • Pour l'instant je filtre les fréquences entre 250 et 350Hz (fréquences de la caisse claire environ).
  • Pour cela, je regarde chez moi sur le logiciel de calcul scilab les coefficients d'un tel filtre :
    • Filtre passe bande,
    • Fréquence de coupure haute : 350Hz,
    • Fréquence de coupure basse : 250Hz,
    • Échantillonnage à 2000Hz (ça devrait suffire), sur 8 bits.
  • Quand je trace la caractéristique d'un tel filtre pour un grand nombre de coefficients, je vois qu'il me faut une cinquantaine de coefficients pour avoir un filtre correct.
  • Je peux donc en séance projet implémenter mon code avec 50 coefficients.

Choix de l'algorithme :

  • Le problème du filtrage temps réel se pose : je ne peux pas stocker en mémoire tout le morceau puis envoyer un signal à chaque fois que je détecte un beat par re-lecture. Il faut les détecter en temps réel.
  • Je vais donc faire la conversion d'un temps très court de musique pour pouvoir le stocker en mémoire vive (je stocke 50 échantillons).
  • Puis je filtre ces 50 échantillons. (Note : pour cela j'ai besoin des 50 échantillons précédents; les 50 premières valeurs en sortie de filtre ne seront donc pas bonnes).
  • Je recommence avec 50 nouveaux échantillons, ad infinitum.
  • Étant donné que la fréquence de l'horloge est de 50MHz et que les beats arrivent au maximum toutes les demies secondes, l'algorithme devrait être assez rapide.

Neuvième Séance (24/03/2011) -- 2h

Arduino

Câblages et test de code Lilypad. Problème rencontré: les puces zigbee semblent ne pas communiquer ensemble à cause d'un changement de canal de transmission: à vérifier à la prochaine séance.

Prochaine séance: câblage des éléments Lilypad.

Plateforme Altium
Je continue les tests sur le filtrage. J'essaie de localiser des endroits précis de musique où il y a des basses, qui devraient apparaître en sortie de filtre.

Dixième Séance (28/03/2011) -- 2h

Arduino

Problème des puces zigbee résolu: cela venait bien d'un changement de canal de transmission. On a donc changé les paramètres grâce au logiciel X-CTU. Amélioration du code Câblage du Lilypad reporté à des séances ultérieures

Plateforme Altium :

  • Les données reçues en sortie de filtre ressemblent bien à des signaux mais ceux-ci restent tous du même ordre de grandeur.
    Soit ils sont tous trop grand et mon filtre ne filtre rien, soit il sont tous faible et je ne détecte aucune basse.
  • Je met en place une fonction qui joue la sortie du filtre (on sait jamais, des fois qu'on puisse discerner une basse parmi le bruit), mais le résultat n'est pas satisfaisant.
  • Je remet en question la bande passante de mon filtre, elle est peut être trop large et trop haute en fréquence.

Onzième Séance (31/03/2011) -- 2h

Arduino

Problème de pause entre chaque cycle de vibrations

Plateforme Altium :

150 coefficients pour coller au gabarit du filtre
  • Je décide de changer mes coefficients pour qu'ils correspondent à un nouveau type de filtre :
    • Filtre passe bande toujours
    • fréquence de coupure haute 80Hz
    • fréquence de coupure basse 50Hz
    • Même échantillonnage à 2000Hz sur 8 bits
  • Il me faut cette fois ci 150 échantillons environ.
  • Pour déterminer ces nouveaux coefficients ne me suis aidé du logiciel audacity qui me permet de faire entre autre une alanyse spectrale de mon signal : sur un morceau de musique donné (celui que je test, avec des battements de grosse caisse évidents et réguliers), je remarque un pic (en puissance (dB)) à 75Hz.
Résultat :
  • Les données reçues en sortie de filtre me laissent toujours perplexe :
  • Visiblement le filtrage fonctionne puisque d'une part plus mon signal est fort (donc plus de puissance), plus je reçois de puissance en moyenne en sortie de filtre, et d'autre part, les données en sortie de filtre sont plus faibles sur des morceaux sans basses (testé avec un caprice de Paganini au violon - fréquences variant autour de la corde de la à 440Hz) que sur des morceaux saturés de basses (double pédale sur du métal).
  • Mais sur mon morceau test avec ses basses claires et régulières, je ne vois pas de changement particulier lors de l'arrivée d'une basse.

Douzième Séance (4/04/2011) -- 2h

Arduino

Problème de pause entre chaque cycle de vibrations : ce problème était du au fait qu'après incrémentation de la variable nbStep jusqu'à 6, on la réinitialisait à 0 au lieu de 1. le switch de notre code ne proposant aucune action pour un nbStep=1 on passait la boucle sans rien faire.

Plateforme Altium :

  • Je décide de ré-examiner mes valeurs reçues dès l'enregistrement audio.
  • En faisant plus attention aux valeurs de bruit que j'obtenais (valeurs supérieures à 190), je remarque qu'en fait ce sont des nombres négatifs complémentés à 2, envoyés par le CAN. En effet, plus le signal est puissant en entrée, plus la sortie du CAN varie autour de zéro et plus les valeurs hautes s'éloignent de 255. Ces valeurs hautes sont donc bien des valeurs négatives.
  • Je met en place une fonction qui me renvoie ces données sur des entiers non signés.

Treizième Séance (5/04/2011) -- 4h

Arduino

Il y avait une problème au niveau du changement de mode sur la platine Arduino: lorsque qu'on changeait de mode en plein milieu d'un cycle de vibration le cycle suivant ne faisait que trois vibrations puis s'arrêtait et recommençait quelques minutes après. Après divers tests, j'ai remarqué que ce problème apparaissait à cause d'une instruction delay() pour les pas 3-et-4 puis 5-et-6. Pour bien respecter les temps entre deux beats il fallait inclure la vibration pour le temps "et" qui n'est pas sur un beat marqué, de façon à ne pas râter les beats suivants (les beats 4 et 6). Or le délai que je calculais entre la fin d'activation des vibreurs pour les beats 3 et 5 et l'activation des vibreurs pour les temps "et" était parfois négatif. Le calcul que j'effectuais était le suivant:

attente entre 3 et "et"=((delta/2) - temps d'activation vibreur).

cycle de vibration des vibreurs

Pour une raison qui m'est encore inconnue, lors d'un changement de mode, quelque soit le sens du changement (mode femme --> mode homme, mode homme --> mode femme), le temps delta/2 était inférieur à mon temps d'activation des vibreurs(delta est calculé à partir d'une mesure de t1 et t2 les temps relevés grâce à la fonction millis() lors des beats 1 et 2). La fonction delay() que j'utilisais prenait donc un argument entier signé négatif transformé en entier non signé (la fonction delay() prend un unsigned long en paramètre) ce qui donnait des chiffres incohérents (par exemple au lieu d'avoir un délai de 200ms j'avais un délai de 10000ms voire beaucoup plus) j'ai donc changé ma gestion des activations et désactivations des vibreurs en partant du principe qu'une pause est toujours égale à delta/4. Le temps "et" se trouvant à delta/2 il suffisait d'attendre à nouveau delta/4 pour activer les vibreurs pour les temps "et". Grâce à cette technique le système s'adapte à n'importe quel tempo (initialement j'avais créé des temps de pauses particuliers pour des rythmes de 60bpm et 120bpm) .


Plateforme Altium :

changement de l'échelle pour l'échantillonage
  • Suite à la modification des entiers reçus en sortie du CAN, je n'ai plus ces valeurs excessivement hautes. Le signal en sortie devient du CAN devient beaucoup plus propre.
  • Problème : maintenant lorsque je n'envoie rien, la valeur de mon signal en sortie du CAN est de 128 (le milieu entre 0 et 255). Pour ne pas que cela perturbe mes mesures ulétrieures (bien que en théorie cela ne devrait pas perturber le filtrage), je change ma fonction qui me renvoie un entier non signé pour qu'elle me renvoie cette fois-ci des entiers signés (mais cohérents : de -128 à 127, et pas de 0 à 127 puis 128 à 255 pour les entiers négatifs).
  • Poursuite des tests.

Quatorzième Séance (7/04/2011) -- 2h

Arduino

Schéma de câblage des éléments Lilypad

début de couture des éléments Lilypad sur le t-shirt

Plateforme Altium :

Apparition d'une basse au début ?
  • J'imprime sur le tableur d'open office les valeurs de mon signal filtré. Je fais quelques graphes avec plusieurs musiques différentes (avec basse, sans basses, plus fort, moins fort, ...). Les résultats semblent cohérents et j'ai même un graphe prometteur qui me renvoie une puissance de sortie 100 fois supérieure à la moyenne pour un temps assez court, ce qui me laisse penser que ça pourrait être une basse.

Quinzième Séance (11/04/2011) -- 2h

Plateforme Altium :

  • Réalisation de nouveaux tests. Le filtrage semble fonctionner (les valeurs retournées lorsqu'il n'y a pas de basses sont presque nulles, et augmentent lorsqu'il y en a - pour un volume sonore donné). Mais il reste très difficile de détecter les basses en soi lorsqu'elles arrivent
  • Mise en place de l'envoi d'un signal +5V ainsi que l'affichage des leds lors de la détection d'une basse. Reste à détecter la basse en question....

Seizième Séance (12/04/2011) -- 4h

Arduino :

voici le t-shirt après quelques coutures:

Couture debut.jpg

Plateforme Altium :

  • Poursuite des tests, toujours dans le but de déterminer une basse de manière explicite...
  • J'encode les informations binaires sur 32 bits au lieu de 8bits, mais cela n'apporte pas plus de résultats. Même la qualité lecture par la nanoboard n'en est pas grandement affectée.
  • Je pense déterminer le principal problème : le temps de filtrage (calcul de 150 valeurs qui nécessitent chacune 150 multiplications => au moins 22500 opérations) est trop long par rapport au temps de lecture, peut être que trop d'informations sont perdues entre deux filtrages

Séances Bonus

Arduino :

Fin des coutures, légère modification du programme pour l'adapter à certains éléments notamment la led RVB Lilypad et l'interrupteur 2 positions. Lors des tests le programme de fonctionnait pas correctement: une fois implanté dans le Lilypad parce qu'avec les coutures effectuées le module Xbee était sous alimenté (il recevait environ 2,2V alors que la tension d'alimentation minimale est de 2,8V) il faut donc alimenter le module sans passer par des protoboards intermédiaires pour éviter les chutes de tension.

t-shirt final

Plateforme Altium :

  • Je change mon code, certaines valeurs n'étaient pas effacées après traitement, ce qui faussait le résultat après plusieurs secondes de filtrage.
  • Redéfinition du filtre : J'agrandi un peu la bande passante de 40 à 75Hz. J'ai à présent 100 coefficients.
  • J'envisage le multi thread en espérant accélérer le processus de filtrage (les multiplications). Mais j'abandonne vite l'idée : dans tous les cas de figure j'aurai des ressources partagées entre les deux threads, et comme les deux threads ne peuvent accéder à la ressource en même temps, l'un attendra toujours pendant que l'autre s'exécute.
  • Une autre solution est de monter la fréquence d'horloge. Mais cette méthode ne fonctionne pas non plus, la nanoboard n'est pas en mesure d'établir de route assez courte dans le fpga pour permettre une fréquence plus rapide. D'après le rapport d'Altium Designer établi après le 'place and route' et la génération du bit file dans le fpga, il est sûr de fonctionner correctement à une fréquence maximale de 40MHz. Je test en descendant la fréquence d'horloge à 40Mhz des fois que mes données soient corrompues à 50Mhz mais je n'obtiens pas de changements. Je reste donc à 50Mhz.
  • Un problème qui peut intervenir aussi, mais qui n'est pas majeur, est un mauvais échantillonnage qui entrainerait des fausses données à basses fréquences, après l'échantillonnage : j'échantillonne à 2000Hz, ce qui est suffisant pour les basses fréquences. Mais pour les plus hautes fréquences, l'échantillonnage ne veut plus rien dire (pour une fréquence à 10kHz, on échantillonnerait une période sur 5). Cela peut en plus créer des faibles basses fréquences, qui n'en sont pas à la base (aliasing).
  • Pour résoudre le problème d'aliasing, il faudrait échantillonner à au moins 44kHz, mais avec cela on augmenterai ne nombre de coefficients, donc le temps de calcul, et en plus on échantillonnerait moins de temps de musique à la fois. Je ne peux pas me le permettre vu que le calcul est déjà long avec les paramètres actuels
  • L'idéal serait de mettre au point une accélération matérielle pour les multiplications, ce qui augmenterait considérablement le temps de calcul pour le filtrage (bien que cela baisse probablement la fréquence d'horloge du processeur). L'accélération matérielle consiste à sous traiter certaines opération du processeur par le fpga même, qui peut lui les effectuer en parallèle. Malheureusement j'ai eu connaissance de cette option assez tard et je n'ai pas réussi à la mettre correctement au point sur la nanoboard. Cela m'aurait permis en plus d'augmenter ma fréquence d'échantillonnage pour limiter au maximum le phénomène d'aliasing.


signal filtré

Au final j'arrive à détecter des beats, mais il reste deux points noirs :

  • Tous ne s'affichent pas, quelques uns ne doivent pas être enregistrés du fait du temps de filtrage
  • Ceux qui arrivent à s'afficher le font avec quelques dixièmes de seconde de latence.