Music Box nano RFID

Bonjour

après la création du programme de lecture écriture dans une carte RFID, la suite et ce pourquoi il a été créé.

Idée: Réaliser une Music Box basée sur arduino tone() et avec mélodie interchangeable.
Les mélodies sont codées dans la zone données d'une carte RFID Mifare 1 K.

j'ai pas inventé la roue ...

le schéma est des plus classique.

ce qui donne

les mélodies sont affichées sur l'OLED

titre auteur nombres de notes et tempo.

codage de la carte RFID

les notes et leurs durées (blanche, noires etc ..) sont codés sur 2 octets.
Dans le programme les fréquences sont dans un tableau en PROGMEM on a juste donc besoin de l'indice, idem pour les durées recalculées a partir de la tempo.

Optimisation du codage de la mélodie sur une idée de fdufnews avec l'aide de terwal
qu'ils soient remerciés.

la mélodie est codée par triplet 3 octets pour 2 notes et 2 durées.

un exemple de dump

[]|00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15
00|C3|D5|1A|E5|E9|08|04|00|62|63|64|65|66|67|68|69
01|20|20|20|20|42|61|64|69|6E|65|72|69|65|73|20|20
02|20|20|20|4A|2E|20|53|2E|20|42|61|63|68|20|20|20
03|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
04|EA|00|78|3D|40|8A|3D|38|A8|3D|38|AA|34|38|8A|34
05|31|A6|2C|31|AA|34|31|AA|33|31|AA|33|31|AA|30|33
06|AA|36|33|AA|34|31|88|3D|40|8A|3D|38|A8|3D|38|AA
07|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
08|34|38|8A|34|31|A6|34|34|88|34|34|88|3D|34|88|34
09|33|88|38|38|88|38|38|88|40|38|88|38|35|88|33|38
10|AA|3B|38|AA|3A|38|AA|3A|38|AA|35|3A|AA|3D|3A|AA
11|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
12|3B|3A|AA|3B|3A|AA|38|3B|AA|38|35|AA|38|3D|AA|38
13|35|AA|38|3F|AA|38|35|AA|38|40|AA|38|35|AA|38|40
14|AA|3F|3D|AA|3F|3B|AA|3A|38|AA|3B|3A|88|38|00|66
15|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
16|38|3B|8A|38|33|A8|38|33|AA|2F|33|8A|2F|2C|A6|32
17|31|88|36|35|8A|38|3B|A8|39|38|AA|39|36|88|39|3D
18|8A|39|36|A8|39|36|AA|33|36|8A|33|2F|A6|2F|34|AA
19|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
20|38|34|AA|36|34|AA|36|34|AA|33|36|AA|39|36|AA|38
21|36|AA|38|36|AA|34|38|AA|34|33|AA|34|39|AA|34|33
22|AA|34|3B|AA|34|33|AA|34|3D|AA|34|33|AA|34|3D|AA
23|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
24|3B|39|AA|3B|38|AA|36|34|AA|38|36|88|34|38|68|38
25|38|88|38|40|88|38|38|88|36|36|88|36|36|88|36|3F
26|88|36|36|88|34|3D|88|40|3D|AA|3B|39|86|39|3D|8C
27|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
28|3B|39|CC|38|36|C6|36|39|8C|38|36|CC|34|32|CA|36
29|39|AA|36|32|AA|31|32|AA|31|30|A8|2C|2D|88|2C|31
30|88|30|33|AA|36|34|8A|33|34|A8|31|33|CC|34|36|CC
31|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
32|38|34|8A|38|3D|A8|38|36|8A|34|33|AA|34|33|A8|31
33|00|66|00|00|00|00|00|00|00|00|00|00|00|00|00|00
34|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
35|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
36|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
37|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
38|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
39|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
40|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
41|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
42|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
43|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
44|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
45|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
46|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
47|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
48|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
49|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
50|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
51|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
52|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
53|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
54|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
55|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
56|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
57|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
58|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
59|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF
60|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
61|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
62|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
63|00|00|00|00|00|00|FF|07|80|69|FF|FF|FF|FF|FF|FF

badinerie de JS Bach 234 notes tempo 120

les blocs 1 et 2 contiennent titre et auteur.

le tout sera mis dans une boite


en cours de réalisation.
la carte s’insère devant dans une fente et la manivelle (encodeur) sera juste a coté.

pour coder les mélodies j'ai réalisé un petit programme Lazarus qui ouvre un xmlmusic en retire les notes et encode suivant le format il peut aussi jouer la mélodie mais le beep() Windows est pas vraiment au point ...

Je sais qu'il existe des trucs assimilé orgue de barbarie qui jouent des mélodies a partir d'une carte sd mais je voulais qq chose qui rappelle un peu les bandes perforées sur lesquelles etait "gravé" la musique. je ne suis pas musicien et je suis bien incapable de réaliser de telle carte ou de pointer un cylindre ..
. et puis ca a déjà été fait ...

pas de circuit imprimé pour cette réalisation ... faire un circuit pour y mettre juste des connecteurs aucun intérêt ! tout sera fixé a l'intérieur et câblé a partir du support nano (un peu plus proprement .... :expressionless: )

toute la partie électronique et programme fonctionne .. reste plus que la menuiserie et la déco ...

fichiers avec musique de J.S. Bach
MusicBox.zip (10.0 KB)

1 Like

Bonsoir jfs59

Peut-être pas, mais quelle belle réalisation et surtout originale, un carte RFID comme support, top :+1:

Cordialement
jpbbricole

Bonjour et merci

Il a fallu faire des choix tant au niveau des notes ( se limiter a 16 ou garder tout) qu au niveau des durées (j'ai tout gardé)
Aussi dans l organisation des données dans la carte. Sacrifier 2 blocs pour y loger les titres et auteurs puis deux octets pour la fin de melodie.
Mais ca laisse pas mal de place.
Il a fallu gerer aussi la memoire ram
Puis rajouter l oled. J ai essayé d utiliser des solutions plus ou moins innovantes et je ne pense pas que le support rfid pour melodie ai deja été utilisé. En tout cas j ai rien trouvé.

Ensuite trouver les melodies comme challenge supplémentaire.
Apprendre a decoder un xml music et a recoder pour la rfid.
Surtout pour qq1 qui n avait aucune notion de solfège.

A titre personnel, je trouve dommage d'avoir peint ton contreplaqué et pas juste fini avec un fond dure et une huile.

J'ai l'impression que tu as quelque redondance d'octet?
As tu penser à essayer d'utilise/tester une compression simple?

Sinon super projet et très original, bravos :clap:

la c'est juste du gesso pour colmater.
En fait les bois utilisés sont de la récup ... et je veux peindre le tout pour ensuite faire une déco style japonisante avec des contours imprimés en abs (voir le contour écran) et peint couleur Or. (après les gouts et couleurs ...)

Voila une idée intéressante .... a voir ce qu un arduino nano peut faire de ce coté.

mais il faudrait que je décompresse a la volée lors de la lecture.
actuellement j'ai déjà çà.

unsigned char melody[720];

je lis l'intégralité de la carte . moins le secteur 1 que je lis séparément et les trailers qui sont inutiles

a partir de la comment indexer une décompression a la volée ??

en fait je dispose de 359 notes ce qui est déjà très bien pour une mélodie.

Oui, je pense que c'est le plus approprié.

Tu as quoi comme code?
Je partirais, sur un double buffer, tu lis dans un buffer relativement petit et tu copies les octets au fur et à mesure de la décompression dans le buffer final.

Mais en fait, il faudrait commencer, à voir si ça un intérêt d'avoir plus de place ?
Si tu pars là dessus, tester en Pascal l'espérance de compression réalisable et voir si cela est toujours intéressant par rapport à ce que cela permet.
Ensuite faire par exemple un programme de test pour voir ce que cela donne en terme de temps ajouté.
Si par exemple on prend un truc simpliste, tout octet supérieur à 0x90, donne le nombre de fois(xFF-0x90) à répéter le caractère suivant.
Je ne pense pas que cela rajoute trop de temps de traitement, mais le pouvoir de compression est très spécifique.

justement pas sur du tout je peux caser des mélodies relativement importante déjà.
dans l'ideal si je pouvais retrouver une note (la 10ieme par exemple) a partir du fichier compressé sans tout décompresser ... mais ça me parait peu probable pour pas dire impossible.
mais je suis pas spécialiste des algo de compression donc ....

Dans ce cas ne te prends pas la tête, c'est juste une mauvaise idée de ma pars.
Il m'avait semblais que tu avais réduit des objectifs, pour être sûre de pouvoir contenir tes mélodies.
Par exemple, il semblais que tu avais parlé d'une restriction sur la gamme de note possible ?

tu l'a peut être dit, tu gère des accords ou des notes simultanées?

pas de note simultanées je voulais en rester a la fonction tone .. sinon il n'y avait plus de limites et je partais sur un orgue et ça a déjà été réalisé et sur un autre support que RFID.
Éventuellement je sais faire mais aucun intérêt.

Il m'avait semblais que tu avais réduit des objectifs, pour être sûre de pouvoir contenir tes mélodies.

Oui mais sans perte comparé aux trucs tone préexistant.

const uint16_t frequenceNotes[] PROGMEM =
{ 0, 31, 33, 35, 37, 39, 41, 44, 46, 49, 52, 55, 58, 62, 65, 69, 73, 78, 82, 87, 93, 98, 104, 110, 117, 123, 131,
139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247, 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494,
523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661,
1760, 1865, 1976, 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951, 4186, 4435, 4699, 4978
};

a noter qu il manque des notes (Bach me la prouvé ...)

c'est quoi la note à 0Hz :face_with_hand_over_mouth:
j'ai trouvé un document sur le net, ou il y a la liste des notes et leur fréquence et la correspondance midi, je ne sais pas si ca peut t'aider :slight_smile:

Bonjour @jfs59
Beau projet mais il manque le plus important : le code complet.

Bonne journée

0hz permet de faire une pause ensuite la duree permet d exprimer le soupir etc...

Ah oui ca m’aide en fait bach colle de mi bemol ES5 partout et en fait il faut le coder en ré diese simplement de ce que j ai compris
1244 ou 1245 c est kif kif enfin pour moi qui suis sourd comme un pot

Ba en fait comme tu prends la gamme du Do majeur, tu as un ton entre le ré et le mi.
Donc si tu baisse le mi d'un demi-ton(bémol, 2-0.5), c'équivalent à augmenter d'un demi-ton le ré(dièse 1+0.5), 2-0.5=1+0.5
Donc pour toutes les notes qui on un ton d'écarts dans ta gamme, tu aura cette égalité.
A quel note correspond les fréquences du coup le 1244 et le 1245 et tu pris ta référence ou ?

1245 c est ce que jai dans ma liste 1244 c est la frequence du mi bemol faut juste que je recode le es5 qui n apparait pas dans ma liste de correspondance faut que je regarde ca de pres car je codais es5 en e5 comme approximation. Comme je disais je suis pas musicien j ai juste des rudiments de solfege et du codage xmlmusic.
Faut que je jongle avec la représentation internationale car en fait il ne manque peut etre pas de notes faut juste bien les recoder. Et ca en pascal je sais faire c est juste adapter des lignes de codes dans le programme en lazarus.

Je viens de revoir différents exemples d arduino song et je viens de m appercevoir d un decalage dans les notes suivant les exemples qui me font penser que mon codage est décalé faut que je revoie tout ca sérieusement. J ai pris un tableau qui ne semble pas correct ce qui expliquerais le decalage observé avec le beep Windows :woozy_face:

image

A priori, tu codes une note dans 1 octets + un quartet. Donc sans compression tu utilises 2 octets par note.
Une compression pas chère consisterait tout simplement à faire sauter tout ces 0 inutiles et coder 2 notes sur 3 octets.

Oui le tempo ne depasse jamais l index 15
Donc je pourrais effectivement coder
Note1 note2 (tempo1,tempo2) je gagne donc 1 octet toutes les deux notes et j ai pas besoin de decompression
Ou alors note1 (t1,t2 ) note2
Ou note1 (t1,note2H) (note2L,t2)

Voila un truc intéressant... reste a choisir la bonne formule

Merci

Y a surement une structure a declarer pour gerer ca facilement

Faut pas que je retrouve un FF fin de melodie faut donc changer ca aussi

Ca me ferais un total de 478 notes possibles au max plus fin de fichier et tempo sur 3 octets

Bon ca merdé sur la tablette j ai delete et la copie m a barré la ligne...

modifications en cours avec le premier triplet qui servira d’entête fichier

typedef struct
{
  uint8_t Note_1;
  uint8_t Note_2;
  uint8_t Duree_Note_2: 4, Duree_Note_1: 4;
} DOUBLE_NOTE;

typedef struct
{
  uint16_t Nombre_notes;
  uint8_t Tempo; 
} ENTETE;

typedef struct
{
  union
    {
        ENTETE entete;
        DOUBLE_NOTE double_note;
    };
} TRIPLET;

utilisation des pointeurs

 void *p; int saut; int frequence; int duree;
  p = &melody;
  pointer_triplet = p;
  saut = ceil(note / (float)2 );
  pointer_triplet += saut; // faudra gérer l’entête ici décalage de 1

  if (note & 1) {
    frequence = pgm_read_word_near(frequenceNotes + pointer_triplet->double_note.Note_1);
    duree = duree_Note[pointer_triplet->double_note.Duree_Note_1];
  } else {
    frequence = pgm_read_word_near(frequenceNotes + pointer_triplet->double_note.Note_2);
    duree = duree_Note[pointer_triplet->double_note.Duree_Note_2];
  }

  HP_Tone (frequence , duree);

ca a l'air de fonctionner même si ca fait bizarre de jouer une carte qui n'a pas été encodée car évidemment la plupart des notes sont fausses

Donc excellente proposition

Après faut voir si je peux améliorer car déclarer un pointer void le faire pointer sur un tableau de char pour ensuite l'affecter au pointer triplette ... je m'interroge.
mais remplir mon tableau char a partir de la carte est si facile ....

      // copier le secteur en memoire
      memcpy(&melody[plage], readBlockData, 16);
      plage += 16;

En tous cas merci beaucoup.

Pourquoi tu n'affectes pas directement melody à pointer_triplet ?
Si ta structure est fixe, tu peux faire un truc du genre

type struct{
    uint16_t NBNotes;
    uint8_t Tempo;
    char* data;
}

tu peux alors affecter une variable de type DOUBLE_NOTE* avec data, puis décaler ce l'adresse pointer sur d'une valeur de size(DOUBLE_NOTE)

je ne sais pas si je suis claire ?

le compilateur il veut pas attribuer un pointer sur char a un pointer sur la structure

pour le reste j'ai pas trop compris non .... je suis pas spécialiste de ce genre de truc j'ai toujours eu du mal avec ca ...

ma melodie est déclarée
unsigned char melody[720];
TRIPLET *pointer_triplet ;

donc j'ai utilisé l'astuce du pointer void
et si je déclare melody comme un tableau de triplet lors du remplissage a partir de la carte ca être le même problème (chef on tourne en rond chef ) mais comme je dis je suis pas spécialement a l'aise avec ce truc.