I2L 2024 Groupe6
Proposition de système
Un clavier midi constitué de 12 touches permettant de produire du son, 2 touches permettant d'augmenter ou diminuer d'une octave, et un bouton permettant de gérer le volume. Un écran affiche l'octave (de 0 à 7) et le volume (de 0 à 100).
Contre-proposition
OK pour la proposition mais il est demandé impérativement d'implanter un périphérique USB de classe MIDI.
Pour la gestion des touches en matrice voyez le projet [1].
Pour la gestion de l'écran LCD vous pouvez vous inspirer du code des groupes 3 et 4 I2L en 2023/2024.
La démonstration MIDI de la bibliothèque LUFA semble être adaptée au projet. Vous pourriez d'ailleurs ajouter une fonctionnalité de cette démonstration consistant en le changement d'instrument. Pour cela vous pouvez utiliser une combinaison de touches comme appuyer simultanément sur un bouton de changment d'octave et sur une touche du clavier.
Si vous avez accès à un imprimante 3D vous pouvez tenter la fabrication de capuchons de touche à mettre sur les boutons poussoirs KAILH, regardez par exemple [2].
Proposition définitive
Clavier MIDI :
4x4 boutons en matrice dont
- 12 boutons de touches de piano
- 2 boutons pour changer d'octave
- un potentiomètre pour régler le son
Un écran LCD pour afficher l'octave sur laquelle on est actuellement.
Le code doit utiliser une bibliothèque permettant de bancher le clavier en MIDI et de le passer en USB pour le lire sur une application adaptée.
Répartition du travail
Carte
Schéma initial
- schéma : Fichier:I2L-2024-Carte-G6a.zip
Carte routée
Composants
- ATmega32u4 : disponible
- quartz GND24 : disponible
- perle ferrite MH2029-300Y : commandée
- potentiomètre écran : disponible
- potentiomètre volume : disponible
- connecteur femelle 16 contacts : commandé
- écran LCD 2 lignes : commandé
- touches KAILH BOX-BLACK : disponibles
Carte au 23/02/2025
Carte au 27/02/2025
Non encore réalisé :
- ajouter la perle de ferrite.
Carte au 07/03/2025
Fontionnement
La carte est un clavier MIDI, cela permet d'émuler un instrument sur un logiciel de MAO (Musique assistée par Ordinateur).
La carte possède :
- 18 touches de piano
- Un potentiomètre, qui peut être affecté à n'importe qu'elle fonction dans le logiciel (volume, effets...)
- Deux touches + et - permettant d'augmenter ou de diminuer l'octave (de 1 à 7). En appuyant simultanément sur les touches, le clavier bascule en mode sélection d'instrument, et les 2 boutons permettent de cycler entre les instruments.
- Un écran LCD permettant de visualiser l'instrument, le volume (ou autre fonction) actuel, l'octave actuelle.
Les instruments disponibles sont :
- Piano
- Pad (Famille de son d'un synthétiseur)
- Trompette
- Violon
- Basse
- Guitare
- Percussion
- Drums (Batterie)
Au niveau du clavier, l'oublie de diodes sur la matrice de boutons fait que nous ne pouvons appuyer que sur 2 boutons simultanément au maximum, sinon nous avons des boutons fantômes.
Nous avons également un problème électrique au niveau du potentiomètre qui va de 0V à environ 0.7V au lieu de 5V, de plus il n'est pas linéaire ce qui ne le rend pas facile à utiliser.
Pour tester la carte:
- En ligne: https://signal.vercel.app/edit, ce site permet de jouer de la musique, de tester le changement d'instrument et d'octave.
- Logiciels de MAO utilisés: Ableton, FL Studio, ce sont des logiciels payant qui permettent de tester le potentiomètre
Nous avons eu besoin des 2 plateformes pour tester la carte, car les sites web permettant de jouer du MIDI sont minimalistes, et acceptent les fonctions MIDI de base comme le changement d'instrument. En revanche, ils ne prennent souvent pas en compte le potentiomètre. Les logiciels de MAO eux, ont tendance à ignorer les fonctions prédéfinies par le MIDI (notamment la sélection d'instrument et des effets), car ils gèrent cela eux même, c'est pourquoi notre potentiomètre est configuré pour envoyer des données sur le canal MIDI 14, qui n'est assigné à rien. L'association du potentiomètre à une fonction se fait dans le logiciel. Nous pouvons quand même utiliser le clavier et changer les octaves.
Ressource utiles :
Listes des commandes disponibles dans MIDI pour le potentiomètre : https://anotherproducer.com/online-tools-for-musicians/midi-cc-list/
Liste des commandes MIDI non assignées : https://anotherproducer.com/online-tools-for-musicians/midi-cc-list/#undefined
Liste des instruments disponibles dans MIDI : https://musicordes.fr/tableau-des-128-instruments-general-midi/
Logiciel qui permet de voir toutes les entrées sorties MIDI d'un périphérique, utile pour programmer: https://hautetechnique.com/midi/midiview/
Code
Nous avons modifié le template MIDI fournit dans la lufa pour plus de lisibilité:
A la racine nous avons le dossier lufa sur lequel nous n'avons rien modifié, et le dossier app/ avec :
- Hardware.c : Initialisation de l'usb et des entrées sorties, gestion du potentiomètre
- HD44780.c : Fonctions de l'écran LCD
- Keyboard.c : Scan et traitement de l'appui sur les boutons
- Midi.c : Envoi des commandes MIDI et gestions des octaves
- Descriptors.c : Fichier de description du périphérique (fourni avec la lufa)
- Globals.h : Définition des constantes et des struct
- main.c : Boucle principale et définition des variables globales
Quelques extraits de code:
Scan de la matrice de bouton:
void scanKeyboard(void) {
for(uint8_t l = 0; l < NB_LINES ; l++) {
*lines[l].port &= ~(1 << lines[l].bit);
for(uint8_t c = 0; c < NB_COLS; c++) {
int t = l * NB_COLS + c;
if(!(*cols[c].pin & (1 << cols[c].bit))) {
if(!buttonPressed[t]){
buttonPressed[t] = true;
isPressed = t;
isReleased = -1;
toProcess = true;
}
} else {
if(buttonPressed[t]){
buttonPressed[t] = false;
isReleased = t;
isPressed = -1;
toProcess = true;
}
}
}
*lines[l].port |= (1 << lines[l].bit);
}
}
Nous avons créé une structure de données pour lier un bouton à une note MIDI. Par défaut le clavier est sur le 3ème octave.
Table des notes MIDI : https://computermusicresource.com/midikeys.html
// 60 to 71 => Octave 3 in order C, C#, D, D#, E, F, F#, G, G#, A, A#, B
// 72 TO 77 => Octave 4 up to F
NoteMIDI notes[NB_NOTES] = {
{4, 60}, {3, 61}, {1, 62}, {2, 63}, {0, 64}, {9, 65},
{8, 66}, {7, 67}, {6, 68}, {5, 69}, {14, 70}, {13, 71},
{12, 72}, {11, 73}, {10, 74}, {19, 75}, {18, 76}, {17, 77}
};
Concernant le volume (potentiomètre) :
/* Capture the adc value */
unsigned int ad_capture(void){
ADCSRA |= (1<<ADSC); // Start conversion
while(bit_is_set(ADCSRA, ADSC)); // Wait for conversion to complete
return ADCH; // Return 8-bit result (0-255)
}
/* Convert the ADC value to a volume */
uint8_t convert_volume(uint8_t volume, uint8_t maxVolume) {
return (volume * maxVolume) / MAX_POT;
}
/* In the main loop */
uint8_t newReading = ad_capture();
filteredVolume = (FILTER_WEIGHT * filteredVolume) + ((1 - FILTER_WEIGHT) * newReading); // Prevent the oscillation from sending too many messages
uint8_t newVolume = (uint8_t)filteredVolume > MAX_POT ? MAX_POT : (uint8_t)filteredVolume;
if (volume != newVolume) {
volume = newVolume;
lcdVolume = convert_volume(volume, MAX_VOLUME_LCD);
midiVolume = convert_volume(volume, MAX_VOLUME_MIDI);
MIDICommand = MIDI_COMMAND_CONTROL_CHANGE;
HD44780_GoTo(20);
HD44780_WriteInteger(lcdVolume, 10);
HD44780_WriteString(" ");
}
/* Example of MIDI Command sending (Volume here) */
if (MIDICommand == MIDI_COMMAND_CONTROL_CHANGE) {
MIDI_EventPacket_t MIDIEvent = (MIDI_EventPacket_t)
{
.Event = (MIDI_EVENT(0, MIDICommand)),
.Data1 = MIDICommand | MIDI_CHANNEL(1),
.Data2 = 14,
.Data3 = midiVolume
};
Endpoint_Write_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
Endpoint_ClearIN();
Changement d'octave ou d'instrument :
if (isReleased == BUTTON_OCTAVE_UP && toProcess && currentState != WAIT_RELEASE) {
if (mode == MODE_OCTAVE) {
octaveUp();
HD44780_GoTo(31);
HD44780_WriteInteger(octave, 10);
isReleased = -1;
} else if (mode == MODE_INSTRUMENT) {
if (currentInstrument < NB_INSTRUMENTS - 1) {
currentInstrument++;
} else {
currentInstrument = 0;
}
MIDICommand = MIDI_COMMAND_PROGRAM_CHANGE;
HD44780_GoTo(0);
HD44780_WriteString(" ");
HD44780_GoTo(0);
HD44780_WriteString(instruments[currentInstrument].instrumentName);
isReleased = -1;
}
}
Pour charger le programme sur la carte nous avons modifié le makefile pour y ajouter 2 commandes :
- make clean: Nettoie les fichiers de build générés
- make upload: Charge le programme sur la carte
Démonstrations
Démonstration du clavier
Changement d'octave
Changement d'instrument
Exemple de gestion de volume avec le potentiomètre
Exemple d'utilisation du potentiomètre pour changer la forme du signal (sinusoide, signal triangulaire, carré...)
Séquence de démarrage
Rendus
Projet KiCAD : Fichier:I2L-2024-Carte-G6.zip
Programmes : Fichier:I2L-2024-Programmes-G6.zip