Created
September 22, 2025 00:00
-
-
Save ypelletier/c660a416bfc5891755f92eaf5bef90c3 to your computer and use it in GitHub Desktop.
Un clavier de piano (1 octave) est affiché sur l'écran TFT. Les notes touchées sont jouées par un haut-parleur (fonction Tone Arduino)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /**************************************************************************** | |
| Un clavier de piano (1 octave) est affiché sur l'écran TFT. | |
| Les notes touchées sont jouées par un haut-parleur (fonction Tone) | |
| Arduino Uno et shield TFT Adafruit. | |
| Haut-parleur et transistor branché à la broche 8 de l'Arduino. | |
| Plus d'infos sur le blog: | |
| https://electroniqueamateur.blogspot.com/2025/09/mini-piano-arduino.html | |
| ******************************************************************************/ | |
| #include <Adafruit_GFX.h> | |
| #include <Adafruit_ILI9341.h> | |
| #include <Adafruit_TSC2007.h> | |
| #define TFT_CS 10 | |
| #define TFT_DC 9 | |
| Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC); | |
| Adafruit_TSC2007 touch; | |
| #define LARGEURECRAN 240 | |
| #define HAUTEURECRAN 320 | |
| // données pour la calibration du capteur tactile | |
| // varie légèrement d'un écran à l'autre | |
| #define TS_MINX 270 | |
| #define TS_MINY 270 | |
| #define TS_MAXX 3740 | |
| #define TS_MAXY 3600 | |
| // disposition et dimensions du clavier à l'écran | |
| #define largeur 30 | |
| #define longueur 100 | |
| #define margeDroite 50 | |
| #define margeHaut 70 | |
| short noteTouchee = -1; | |
| #define sortieTone 8 // sortie du son à la broche 8 de l'Arduino | |
| // fréquence associée à chaque note | |
| // do, ré, mi, fa, sol, la, si, do#, mib, rien, fa#, sol#, lab. | |
| const float frequ_note[] = {65.41, 73.42, 82.41, 87.31, 98.00, 110.00, 123.47, 69.30, 77.78, 0 , 92.50, 103.83,116.54 | |
| }; | |
| const String noms[] = { "do", "re", "mi", "fa", "sol", "la", "si", "do#", "mib", " ", "fa#", "sol#", "sib" }; | |
| void setup() { | |
| tft.begin(); | |
| touch.begin();A | |
| tft.setRotation(1); //écran en mode paysage | |
| tft.fillScreen(ILI9341_WHITE); | |
| // on dessine le clavier | |
| for (int i = 0; i <= 6; i++) { | |
| tft.drawRect(margeDroite + i * largeur, margeHaut, largeur, longueur, ILI9341_BLACK); | |
| if ((i != 2) && (i != 6 )) { | |
| tft.fillRect(margeDroite + largeur * .7 + i * largeur, margeHaut, largeur * 0.6, longueur * 0.6, ILI9341_BLACK); | |
| } | |
| } | |
| } | |
| void loop() { | |
| uint16_t x, y, z1, z2, temp, touche; | |
| touche = -1; | |
| if (touch.read_touch(&x, &y, &z1, &z2)) { | |
| // transposition en coordonnées sur l'écran 240 X 320 pixels | |
| if (x < TS_MINX) { | |
| x = TS_MINX; | |
| } | |
| if (x > TS_MAXX) { | |
| x = TS_MAXX; | |
| } | |
| if (y < TS_MINY) { | |
| y = TS_MINY; | |
| } | |
| if (y > TS_MAXY) { | |
| y = TS_MAXY; | |
| } | |
| x = map(x, TS_MINX, TS_MAXX, 0, LARGEURECRAN); | |
| y = map(y, TS_MINY, TS_MAXY, 0, HAUTEURECRAN); | |
| temp = x; | |
| x = y; | |
| y = 240 - temp; | |
| // il faut maintenant déterminer si cette position correspond à une touche du piano | |
| // les touches blanches: | |
| if ( (y > margeHaut) && (y < margeHaut + longueur)) { // ni trop haut ni trop bas | |
| for (int i = 0; i <= 6; i++) { | |
| if ((x > margeDroite + i * largeur) && (x < margeDroite + i * largeur + largeur)) { // dans la touche | |
| touche = i ; | |
| } | |
| } | |
| } | |
| // les touches noires: | |
| if ( (y > margeHaut) && (y < margeHaut + longueur * 0.6)) { // ni trop haut ni trop bas | |
| for (int i = 0; i <= 6; i++) { | |
| if ((i != 2) && (i != 6 )) { | |
| if ((x > margeDroite + largeur * .7 + i * largeur) && (x < margeDroite + largeur * .7 + i * largeur + largeur * 0.6)) { // dans la touche | |
| touche = i + 7; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| // rétroaction visuelle: la touche devient rouge pendant qu'elle est appuyée | |
| if (touche != noteTouchee) { // quelque chose a changé | |
| if (touche != -1) { // on vient d'enfoncer une touche | |
| if (touche < 7) { // c'est une touche blanche (il faut la mettre en rouge) | |
| tft.fillRect(margeDroite + touche * largeur + 1, margeHaut + 1, largeur - 2, longueur - 2, ILI9341_RED); | |
| // mais il faut préserver les touches noires voisines | |
| if ((touche != 0 ) && (touche != 3)) { // il y a une touche noire à gauche | |
| tft.fillRect(margeDroite + largeur * .7 + (touche - 1) * largeur, margeHaut, largeur * 0.6, longueur * 0.6, ILI9341_BLACK); | |
| } | |
| if ((touche != 2 ) && (touche != 6)) { // il y a une touche noire à droite | |
| tft.fillRect(margeDroite + largeur * .7 + touche * largeur, margeHaut, largeur * 0.6, longueur * 0.6, ILI9341_BLACK); | |
| } | |
| } | |
| if (touche > 6) { // c'est une touche noire (il faut la mettre en rouge) | |
| tft.fillRect(margeDroite + largeur * .7 + (touche - 7) * largeur, margeHaut, largeur * 0.6, longueur * 0.6, ILI9341_RED); | |
| } | |
| } | |
| if (noteTouchee != -1) { // on vient de relâcher une touche | |
| if (noteTouchee < 7) { // c'est une touche blanche, il faut la remettre en blanc | |
| tft.fillRect(margeDroite + noteTouchee * largeur + 1, margeHaut + 1, largeur - 2, longueur - 2, ILI9341_WHITE); | |
| // il faut aussi restaurer les touches noires voisines: | |
| if ((noteTouchee != 0 ) && (noteTouchee != 3)) { // il y a une touche noire à gauche | |
| tft.fillRect(margeDroite + largeur * .7 + (noteTouchee - 1) * largeur, margeHaut, largeur * 0.6, longueur * 0.6, ILI9341_BLACK); | |
| } | |
| if ((noteTouchee != 2 ) && (noteTouchee != 6)) { // il y a une touche noire à droite | |
| tft.fillRect(margeDroite + largeur * .7 + noteTouchee * largeur, margeHaut, largeur * 0.6, longueur * 0.6, ILI9341_BLACK); | |
| } | |
| } | |
| if (noteTouchee > 6) { // c'est une touche noire, il faut la remettre en noir | |
| tft.fillRect(margeDroite + largeur * .7 + (noteTouchee - 7) * largeur, margeHaut, largeur * 0.6, longueur * 0.6, ILI9341_BLACK); | |
| } | |
| } | |
| } | |
| // affichage à l'écran du nom de la note jouée: | |
| if (touche != noteTouchee) { // il faut changer la note affichée | |
| // effacer la région appropriée | |
| tft.fillRect(125, 180, 100, 50, ILI9341_WHITE); | |
| // si pas -1 alors écrire la nouvelle valeur | |
| if (touche != -1) | |
| { | |
| tft.setCursor(140, 190); | |
| tft.setTextColor(ILI9341_BLACK); | |
| tft.setTextSize(3); | |
| tft.print(noms[touche]); | |
| } | |
| } | |
| // on émet un son qui correspond à la note jouée | |
| if (touche != noteTouchee) { // il y a eu un changement | |
| if (touche == -1) { | |
| noTone(sortieTone); | |
| } | |
| else{ | |
| tone(sortieTone, frequ_note[touche]*2); | |
| } | |
| } | |
| noteTouchee = touche; | |
| delay(100); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment