Skip to content

Instantly share code, notes, and snippets.

@ypelletier
Created September 22, 2025 00:00
Show Gist options
  • Select an option

  • Save ypelletier/c660a416bfc5891755f92eaf5bef90c3 to your computer and use it in GitHub Desktop.

Select an option

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)
/****************************************************************************
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